Skip to content

Commit 975498d

Browse files
author
Martin Belanger
committed
libnvme: Add nvme_getifaddrs()
The POSIX `getifaddrs()` API returns the list of network interfaces on the system, but invoking it can be costly. On large-scale systems with hundreds of NVMe-over-TCP connections, this API may be called hundreds of times, resulting in increased latency. This patch introduces `nvme_getifaddrs()`, a wrapper around `getifaddrs()` that caches the results on the first invocation and reuses the cached data on subsequent calls. Signed-off-by: Martin Belanger <[email protected]>
1 parent 0cfa413 commit 975498d

3 files changed

Lines changed: 48 additions & 3 deletions

File tree

libnvme/src/nvme/tree.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ void nvme_free_global_ctx(struct nvme_global_ctx *ctx)
531531
free(ctx->config_file);
532532
free(ctx->application);
533533
free(ctx);
534+
535+
nvme_getifaddrs(NULL); /* Free cached I/F addresses */
534536
}
535537

536538
void nvme_root_release_fds(struct nvme_global_ctx *ctx)
@@ -1787,9 +1789,9 @@ static ctrl_match_t _candidate_init(struct candidate_args *candidate,
17871789

17881790
if (streq0(transport, "tcp")) {
17891791
/* For TCP we may need to access the interface map.
1790-
* Let's retrieve and cache the map.
1792+
* Let's retrieve the (cached) map.
17911793
*/
1792-
if (getifaddrs(&candidate->iface_list) == -1)
1794+
if (nvme_getifaddrs(&candidate->iface_list) == -1)
17931795
candidate->iface_list = NULL;
17941796

17951797
candidate->addreq = nvme_ipaddrs_eq;
@@ -1813,7 +1815,10 @@ static ctrl_match_t _candidate_init(struct candidate_args *candidate,
18131815
*/
18141816
static void _candidate_free(struct candidate_args *candidate)
18151817
{
1816-
freeifaddrs(candidate->iface_list); /* This is NULL-safe */
1818+
/* iface_list points to cached data owned by nvme_getifaddrs().
1819+
* Do not free here. The memory will be released when we free the
1820+
* global context.
1821+
*/
18171822
}
18181823

18191824
#define _cleanup_candidate_ __cleanup__(_candidate_free)

libnvme/src/nvme/util.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,31 @@ bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const cha
11421142

11431143
#endif /* HAVE_NETDB */
11441144

1145+
int nvme_getifaddrs(struct ifaddrs **ifap)
1146+
{
1147+
static struct ifaddrs *ifaddrs_cache;
1148+
static bool ifaddrs_cached;
1149+
1150+
if (!ifap) {
1151+
freeifaddrs(ifaddrs_cache); /* NULL-safe */
1152+
ifaddrs_cache = NULL;
1153+
ifaddrs_cached = false;
1154+
return 0;
1155+
}
1156+
1157+
if (!ifaddrs_cached) {
1158+
if (getifaddrs(&ifaddrs_cache) == -1) {
1159+
ifaddrs_cache = NULL;
1160+
*ifap = NULL;
1161+
return -1;
1162+
}
1163+
ifaddrs_cached = true;
1164+
}
1165+
1166+
*ifap = ifaddrs_cache;
1167+
return 0;
1168+
}
1169+
11451170
void *__nvme_alloc(size_t len)
11461171
{
11471172
size_t _len = round_up(len, 0x1000);

libnvme/src/nvme/util.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,21 @@ int nvme_uuid_find(struct nvme_id_uuid_list *uuid_list, const unsigned char uuid
758758
*/
759759
bool nvme_ipaddrs_eq(const char *addr1, const char *addr2);
760760

761+
/**
762+
* nvme_getifaddrs - Cached wrapper around getifaddrs()
763+
* @ifap: Output pointer to the cached interface address list. If
764+
* NULL, then free the cache.
765+
*
766+
* On the first call, this function invokes the POSIX getifaddrs()
767+
* and caches the result. Subsequent calls return the cached data.
768+
* The caller must NOT call freeifaddrs() on the returned data.
769+
* Use nvme_getifaddrs() with ifap set to NULL to release the
770+
* cache when done.
771+
*
772+
* Return: 0 on success, -1 on error (with errno set).
773+
*/
774+
int nvme_getifaddrs(struct ifaddrs **ifap);
775+
761776
/**
762777
* nvme_iface_matching_addr - Get interface matching @addr
763778
* @iface_list: Interface list returned by getifaddrs()

0 commit comments

Comments
 (0)