diff --git a/config.h.meson b/config.h.meson index 2bd93ce22..d41304db6 100644 --- a/config.h.meson +++ b/config.h.meson @@ -282,3 +282,6 @@ /* Define if NBFT support is enabled */ #mesondefine WITH_NBFT + +/* Define to 1 if dlvsym() is available */ +#mesondefine HAVE_DLVSYM diff --git a/meson.build b/meson.build index a88012c6b..e13cd9da0 100644 --- a/meson.build +++ b/meson.build @@ -137,6 +137,9 @@ config_h.set10('HAVE_DECL_REALLOCARRAY', cc.has_function('reallocarray', prefix: config_h.set10('HAVE_DECL_EXPLICIT_BZERO', cc.has_function('explicit_bzero', prefix: '#include ')) config_h.set10('HAVE_DECL_MEMFD_CREATE', cc.has_function('memfd_create', prefix: '#include ')) +config_h.set10('HAVE_DLVSYM', cc.has_function('dlvsym', prefix: '''#define _GNU_SOURCE + #include ''')) + # types config_h.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include ')) config_h.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include ')) diff --git a/src/nm-initrd-generator/meson.build b/src/nm-initrd-generator/meson.build index 0e9689f32..6b02e0668 100644 --- a/src/nm-initrd-generator/meson.build +++ b/src/nm-initrd-generator/meson.build @@ -1,15 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -libnmi_deps = [ - libnm_core_public_dep, -] - -if enable_nbft - libnmi_deps += [ - libnvme_dep - ] -endif - libnmi_core = static_library( 'nmi-core', sources: files( @@ -22,7 +12,9 @@ libnmi_core = static_library( src_inc, top_inc, ], - dependencies: libnmi_deps, + dependencies: [ + libnm_core_public_dep, + ], ) executable( @@ -32,7 +24,9 @@ executable( src_inc, top_inc, ], - dependencies: libnmi_deps, + dependencies: [ + libnm_core_public_dep, + ], link_with: [ libnmi_core, libnm_core_aux_intern, diff --git a/src/nm-initrd-generator/nmi-nbft-reader.c b/src/nm-initrd-generator/nmi-nbft-reader.c index 782c6acca..09e5eb12d 100644 --- a/src/nm-initrd-generator/nmi-nbft-reader.c +++ b/src/nm-initrd-generator/nmi-nbft-reader.c @@ -10,6 +10,7 @@ #if WITH_NBFT #include +#include #include "libnm-log-core/nm-logging.h" #include "libnm-core-intern/nm-core-internal.h" @@ -32,6 +33,34 @@ is_valid_addr(int family, const char *addr) && nm_utils_ipaddr_valid(family, addr)); } +static int (*_nvme_nbft_read)(struct nbft_info **nbft, const char *filename); +static void (*_nvme_nbft_free)(struct nbft_info *nbft); + +static void * +load_libnvme(void) +{ + void *handle; + + handle = dlopen("libnvme.so.1", RTLD_LAZY); + if (!handle) + return NULL; + +#if HAVE_DLVSYM + _nvme_nbft_read = dlvsym(handle, "nvme_nbft_read", "LIBNVME_1_5"); + _nvme_nbft_free = dlvsym(handle, "nvme_nbft_free", "LIBNVME_1_5"); +#else + /* no dlvsym() in musl */ + _nvme_nbft_read = dlsym(handle, "nvme_nbft_read"); + _nvme_nbft_free = dlsym(handle, "nvme_nbft_free"); +#endif + + if (!_nvme_nbft_read || !_nvme_nbft_free) { + dlclose(handle); + return NULL; + } + return handle; +} + static NMConnection * parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname) { @@ -225,12 +254,13 @@ parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname) NMConnection ** nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname) { - GPtrArray *a; - gs_free char *path = NULL; - gs_free_error GError *error = NULL; - GDir *dir; - const char *entry_name; - int idx = 1; + nm_auto_unref_ptrarray GPtrArray *a = NULL; + gs_free char *path = NULL; + gs_free_error GError *error = NULL; + GDir *dir; + void *libnvme_handle = NULL; + const char *entry_name; + int idx = 1; g_return_val_if_fail(sysfs_dir != NULL, NULL); path = g_build_filename(sysfs_dir, "firmware", "acpi", "tables", NULL); @@ -250,8 +280,14 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname) if (!g_str_has_prefix(entry_name, "NBFT")) continue; + /* attempt to load libnvme only on the first table match, saving some I/O */ + if (!libnvme_handle && !(libnvme_handle = load_libnvme())) { + g_dir_close(dir); + return NULL; + } + entry_path = g_build_filename(path, entry_name, NULL); - ret = nvme_nbft_read(&nbft, entry_path); + ret = _nvme_nbft_read(&nbft, entry_path); if (ret) { _LOGW(LOGD_CORE, "Error parsing NBFT table %s: %m", entry_path); continue; @@ -274,10 +310,11 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname) g_ptr_array_add(a, connection); } - nvme_nbft_free(nbft); + _nvme_nbft_free(nbft); } g_dir_close(dir); + dlclose(libnvme_handle); g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */ return (NMConnection **) g_ptr_array_free(a, FALSE); }