initrd: avoid dynamic linking of libnvme, use dlopen() instead
As suggested during the review process, NBFT is niche and most users won't need it. So keep the initrd generator light and only open libnvme when any NBFT table is found. In a typical dracut host-only scenario the nbft dracut module will be pulled in only when NBFT is present in the system, packing in nvme-cli and libnvme in the initramfs image. Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
This commit is contained in:

committed by
Beniamino Galvani

parent
1cb0635d08
commit
8b7c6f8b90
@@ -282,3 +282,6 @@
|
|||||||
|
|
||||||
/* Define if NBFT support is enabled */
|
/* Define if NBFT support is enabled */
|
||||||
#mesondefine WITH_NBFT
|
#mesondefine WITH_NBFT
|
||||||
|
|
||||||
|
/* Define to 1 if dlvsym() is available */
|
||||||
|
#mesondefine HAVE_DLVSYM
|
||||||
|
@@ -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 <string.h>'))
|
config_h.set10('HAVE_DECL_EXPLICIT_BZERO', cc.has_function('explicit_bzero', prefix: '#include <string.h>'))
|
||||||
config_h.set10('HAVE_DECL_MEMFD_CREATE', cc.has_function('memfd_create', prefix: '#include <sys/mman.h>'))
|
config_h.set10('HAVE_DECL_MEMFD_CREATE', cc.has_function('memfd_create', prefix: '#include <sys/mman.h>'))
|
||||||
|
|
||||||
|
config_h.set10('HAVE_DLVSYM', cc.has_function('dlvsym', prefix: '''#define _GNU_SOURCE
|
||||||
|
#include <dlfcn.h>'''))
|
||||||
|
|
||||||
# types
|
# types
|
||||||
config_h.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
|
config_h.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
|
||||||
config_h.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
|
config_h.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
|
||||||
|
@@ -1,15 +1,5 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# 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(
|
libnmi_core = static_library(
|
||||||
'nmi-core',
|
'nmi-core',
|
||||||
sources: files(
|
sources: files(
|
||||||
@@ -22,7 +12,9 @@ libnmi_core = static_library(
|
|||||||
src_inc,
|
src_inc,
|
||||||
top_inc,
|
top_inc,
|
||||||
],
|
],
|
||||||
dependencies: libnmi_deps,
|
dependencies: [
|
||||||
|
libnm_core_public_dep,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
@@ -32,7 +24,9 @@ executable(
|
|||||||
src_inc,
|
src_inc,
|
||||||
top_inc,
|
top_inc,
|
||||||
],
|
],
|
||||||
dependencies: libnmi_deps,
|
dependencies: [
|
||||||
|
libnm_core_public_dep,
|
||||||
|
],
|
||||||
link_with: [
|
link_with: [
|
||||||
libnmi_core,
|
libnmi_core,
|
||||||
libnm_core_aux_intern,
|
libnm_core_aux_intern,
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#if WITH_NBFT
|
#if WITH_NBFT
|
||||||
|
|
||||||
#include <libnvme.h>
|
#include <libnvme.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include "libnm-log-core/nm-logging.h"
|
#include "libnm-log-core/nm-logging.h"
|
||||||
#include "libnm-core-intern/nm-core-internal.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));
|
&& 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 *
|
static NMConnection *
|
||||||
parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname)
|
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 **
|
NMConnection **
|
||||||
nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
|
nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
|
||||||
{
|
{
|
||||||
GPtrArray *a;
|
nm_auto_unref_ptrarray GPtrArray *a = NULL;
|
||||||
gs_free char *path = NULL;
|
gs_free char *path = NULL;
|
||||||
gs_free_error GError *error = NULL;
|
gs_free_error GError *error = NULL;
|
||||||
GDir *dir;
|
GDir *dir;
|
||||||
const char *entry_name;
|
void *libnvme_handle = NULL;
|
||||||
int idx = 1;
|
const char *entry_name;
|
||||||
|
int idx = 1;
|
||||||
|
|
||||||
g_return_val_if_fail(sysfs_dir != NULL, NULL);
|
g_return_val_if_fail(sysfs_dir != NULL, NULL);
|
||||||
path = g_build_filename(sysfs_dir, "firmware", "acpi", "tables", 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"))
|
if (!g_str_has_prefix(entry_name, "NBFT"))
|
||||||
continue;
|
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);
|
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) {
|
if (ret) {
|
||||||
_LOGW(LOGD_CORE, "Error parsing NBFT table %s: %m", entry_path);
|
_LOGW(LOGD_CORE, "Error parsing NBFT table %s: %m", entry_path);
|
||||||
continue;
|
continue;
|
||||||
@@ -274,10 +310,11 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
|
|||||||
g_ptr_array_add(a, connection);
|
g_ptr_array_add(a, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
nvme_nbft_free(nbft);
|
_nvme_nbft_free(nbft);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dir_close(dir);
|
g_dir_close(dir);
|
||||||
|
dlclose(libnvme_handle);
|
||||||
g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */
|
g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */
|
||||||
return (NMConnection **) g_ptr_array_free(a, FALSE);
|
return (NMConnection **) g_ptr_array_free(a, FALSE);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user