From aa594f11143c2ca030a965eb3a30ea671d67ac80 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 05:34:06 -0500 Subject: [PATCH 01/32] meson: add option MODULE_ALTERNATIVE_DIRECTORY This option allows the user to specify the alternative directory that the kmod tools should look at when MODULE_DIRECTORY is empty. Defaults to /run/modules. Signed-off-by: Emanuele Giuseppe Esposito --- Makefile.am | 3 ++- configure.ac | 52 +++++++++++++++++++++++------------------ man/Makefile.am | 1 + meson.build | 4 ++++ meson_options.txt | 6 +++++ scripts/setup-rootfs.sh | 1 + testsuite/meson.build | 1 + 7 files changed, 44 insertions(+), 24 deletions(-) diff --git a/Makefile.am b/Makefile.am index 504af5b2..c7aae8e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ AM_CPPFLAGS = \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DDISTCONFDIR=\""$(distconfdir)"\" \ -DMODULE_DIRECTORY=\""$(module_directory)"\" \ + -DMODULE_ALTERNATIVE_DIRECTORY=\""$(module_alternative_directory)"\" \ ${zlib_CFLAGS} AM_CFLAGS = $(OUR_CFLAGS) @@ -198,7 +199,7 @@ MODULE_PLAYGROUND = testsuite/module-playground BUILD_MODULES = $(AM_V_GEN) $(top_srcdir)/scripts/setup-modules.sh $(top_srcdir) $(top_builddir) $(MODULE_PLAYGROUND) ROOTFS = testsuite/rootfs ROOTFS_PRISTINE = $(top_srcdir)/testsuite/rootfs-pristine -CREATE_ROOTFS = $(AM_V_GEN) $(top_srcdir)/scripts/setup-rootfs.sh $(ROOTFS_PRISTINE) $(ROOTFS) $(MODULE_PLAYGROUND) $(top_builddir)/config.h $(sysconfdir) $(module_directory) +CREATE_ROOTFS = $(AM_V_GEN) $(top_srcdir)/scripts/setup-rootfs.sh $(ROOTFS_PRISTINE) $(ROOTFS) $(MODULE_PLAYGROUND) $(top_builddir)/config.h $(sysconfdir) $(module_directory) $(module_alternative_directory) build-module-playground: $(BUILD_MODULES) diff --git a/configure.ac b/configure.ac index 7e35f1be..0af420d8 100644 --- a/configure.ac +++ b/configure.ac @@ -89,8 +89,13 @@ AC_ARG_WITH([module_directory], [], [with_module_directory=/lib/modules]) AC_SUBST([module_directory], [$with_module_directory]) +AC_ARG_WITH([module_alternative_directory], + AS_HELP_STRING([--with-module-alternative_directory=DIR], [alternative directory in which to look for kernel modules @<:@default=/run/modules@:>@]), + [], [with_module_alternative_directory=/run/modules]) +AC_SUBST([module_alternative_directory], [$with_module_alternative_directory]) + # Check all directory arguments for consistency. -for ac_var in distconfdir module_directory +for ac_var in distconfdir module_directory module_alternative_directory do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -335,26 +340,27 @@ AC_MSG_RESULT([ $PACKAGE $VERSION ======= - module_directory: ${module_directory} - prefix: ${prefix} - sysconfdir: ${sysconfdir} - distconfdir: ${distconfdir} - libdir: ${libdir} - includedir: ${includedir} - bindir: ${bindir} - Bash completions dir: ${with_bashcompletiondir} - - compiler: ${CC} - cflags: ${with_cflags} ${CFLAGS} - ldflags: ${with_ldflags} ${LDFLAGS} - - tools: ${enable_tools} - logging: ${enable_logging} - compression: zstd=${with_zstd} xz=${with_xz} zlib=${with_zlib} - debug: ${enable_debug} - coverage: ${enable_coverage} - doc: ${enable_gtk_doc} - man: ${enable_manpages} - - features: ${with_features} + module_directory: ${module_directory} + module_alternative_directory: ${module_alternative_directory} + prefix: ${prefix} + sysconfdir: ${sysconfdir} + distconfdir: ${distconfdir} + libdir: ${libdir} + includedir: ${includedir} + bindir: ${bindir} + Bash completions dir: ${with_bashcompletiondir} + + compiler: ${CC} + cflags: ${with_cflags} ${CFLAGS} + ldflags: ${with_ldflags} ${LDFLAGS} + + tools: ${enable_tools} + logging: ${enable_logging} + compression: zstd=${with_zstd} xz=${with_xz} zlib=${with_zlib} + debug: ${enable_debug} + coverage: ${enable_coverage} + doc: ${enable_gtk_doc} + man: ${enable_manpages} + + features: ${with_features} ]) diff --git a/man/Makefile.am b/man/Makefile.am index 6356d878..d72ba0a6 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -18,6 +18,7 @@ define generate_manpage sed -e 's|@SYSCONFDIR@|$(sysconfdir)|g' | \ sed -e 's|@DISTCONFDIR@|$(distconfdir)|g' | \ sed -e 's|@MODULE_DIRECTORY@|$(module_directory)|g' | \ + sed -e 's|@MODULE_ALTERNATIVE_DIRECTORY@|$(module_alternative_directory)|g' | \ $(SCDOC) > $@ endef diff --git a/meson.build b/meson.build index 7e7c0209..0e2c39cd 100644 --- a/meson.build +++ b/meson.build @@ -193,6 +193,7 @@ datadir = prefixdir / get_option('datadir') distconfdir = get_option('distconfdir') moduledir = get_option('moduledir') +modulealternativedir = get_option('modulealternativedir') bashcompletiondir = get_option('bashcompletiondir') fishcompletiondir = get_option('fishcompletiondir') @@ -204,6 +205,7 @@ _customdirs = [ # The defaults are hard-coded due to historical reasons ['distconfdir', prefixdir / 'lib', 'DISTCONFDIR'], ['moduledir', '/lib/modules', 'MODULE_DIRECTORY'], + ['modulealternativedir', '/run/modules', 'MODULE_ALTERNATIVE_DIRECTORY'], ] foreach tuple : _customdirs @@ -472,6 +474,7 @@ _kmod_variables = [ 'sysconfdir=' + sysconfdir, 'distconfdir=' + distconfdir, 'module_directory=' + moduledir, + 'module_alternative_directory=' + modulealternativedir, ] # Don't (space) escape variables with space-separated lists, for consistency @@ -565,6 +568,7 @@ summary({ summary({ 'distconfdir' : distconfdir, 'moduledir' : moduledir, + 'modulealternativedir' : modulealternativedir, }, section : 'Kmod specific') summary({ diff --git a/meson_options.txt b/meson_options.txt index 3d41fae2..4c466e7b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -12,6 +12,12 @@ option( description : 'Directory to look for kernel modules. Default: /lib/modules', ) +option( + 'modulealternativedir', + type : 'string', + description : 'Alternative directory to look for kernel modules. Default: /run/modules', +) + option( 'bashcompletiondir', type : 'string', diff --git a/scripts/setup-rootfs.sh b/scripts/setup-rootfs.sh index cbf94bc9..707fc87f 100755 --- a/scripts/setup-rootfs.sh +++ b/scripts/setup-rootfs.sh @@ -8,6 +8,7 @@ MODULE_PLAYGROUND=$3 CONFIG_H=$4 SYSCONFDIR=$5 MODULE_DIRECTORY=$6 +MODULE_ALTERNATIVE_DIRECTORY=$7 # create rootfs from rootfs-pristine diff --git a/testsuite/meson.build b/testsuite/meson.build index 1f49f698..e8851a75 100644 --- a/testsuite/meson.build +++ b/testsuite/meson.build @@ -28,6 +28,7 @@ create_rootfs = custom_target( meson.project_build_root() / 'config.h', sysconfdir, moduledir, + modulealternativedir, ], output : 'stamp-rootfs', console : true, From f3aeade62bc404bae8e94d5f229055b0457ea357 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Fri, 31 Jan 2025 05:03:21 -0500 Subject: [PATCH 02/32] meson: add ENABLE_ALTERNATIVE_DIR Add a boolean flag at setup time to let the user decide whether kmod should consider the fallback MODULE_ALTERNATIVE_DIRECTORY or not. If this flag is False, MODULE_ALTERNATIVE_DIRECTORY will be ignored. Signed-off-by: Emanuele Giuseppe Esposito --- Makefile.am | 1 + configure.ac | 4 ++++ meson.build | 17 ++++++++++------- meson_options.txt | 9 ++++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index c7aae8e9..4b9b0afa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ AM_CPPFLAGS = \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DDISTCONFDIR=\""$(distconfdir)"\" \ -DMODULE_DIRECTORY=\""$(module_directory)"\" \ + -DENABLE_ALTERNATIVE_DIR=\""$(enable_alternative_dir) -DMODULE_ALTERNATIVE_DIRECTORY=\""$(module_alternative_directory)"\" \ ${zlib_CFLAGS} diff --git a/configure.ac b/configure.ac index 0af420d8..01d96463 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,9 @@ AC_ARG_WITH([module_directory], [], [with_module_directory=/lib/modules]) AC_SUBST([module_directory], [$with_module_directory]) +AC_ARG_ENABLE([enable_alternative_dir], + AS_HELP_STRING([--enable-alternative-dir], [enable alternative module directory @<:@default=disabled@:>@]), + [], [enable_alternative_dir=no]) AC_ARG_WITH([module_alternative_directory], AS_HELP_STRING([--with-module-alternative_directory=DIR], [alternative directory in which to look for kernel modules @<:@default=/run/modules@:>@]), [], [with_module_alternative_directory=/run/modules]) @@ -341,6 +344,7 @@ AC_MSG_RESULT([ ======= module_directory: ${module_directory} + enable_alternative_dir: ${enable_alternative_dir} module_alternative_directory: ${module_alternative_directory} prefix: ${prefix} sysconfdir: ${sysconfdir} diff --git a/meson.build b/meson.build index 0e2c39cd..51b0762c 100644 --- a/meson.build +++ b/meson.build @@ -193,7 +193,9 @@ datadir = prefixdir / get_option('datadir') distconfdir = get_option('distconfdir') moduledir = get_option('moduledir') +enablealternativedir = get_option('enable-alternative-dir') modulealternativedir = get_option('modulealternativedir') +cdata.set10('ENABLE_ALTERNATIVE_DIR', enablealternativedir) bashcompletiondir = get_option('bashcompletiondir') fishcompletiondir = get_option('fishcompletiondir') @@ -578,13 +580,14 @@ summary({ }, section : 'Shell completions') summary({ - 'tools' : get_option('tools'), - 'logging' : get_option('logging'), - 'debug-messages' : get_option('debug-messages'), - 'build-tests' : get_option('build-tests'), - 'manpages' : get_option('manpages'), - 'docs' : get_option('docs'), - 'dlopen' : get_option('dlopen'), + 'tools' : get_option('tools'), + 'logging' : get_option('logging'), + 'debug-messages' : get_option('debug-messages'), + 'build-tests' : get_option('build-tests'), + 'enable-alternative-dir' : get_option('enable-alternative-dir'), + 'manpages' : get_option('manpages'), + 'docs' : get_option('docs'), + 'dlopen' : get_option('dlopen'), }, section : 'Options') summary({ diff --git a/meson_options.txt b/meson_options.txt index 4c466e7b..a1f06828 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -12,10 +12,17 @@ option( description : 'Directory to look for kernel modules. Default: /lib/modules', ) +option( + 'enable-alternative-dir', + type : 'boolean', + value : false, + description : 'Always use a fallback alternative directory to look for kernel modules. Default: false', +) + option( 'modulealternativedir', type : 'string', - description : 'Alternative directory to look for kernel modules. Default: /run/modules', + description : 'Alternative directory to look for kernel modules, if enable-alternative-dir is true. Otherwise unused. Default: /run/modules', ) option( From c7c0cc022aa9b608a562428b667daf247d0f5add Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 04:22:07 -0500 Subject: [PATCH 03/32] tools/log.h: add macros to catch logs and print them later With the incoming MODULE_ALTERNATIVE_DIRECTORY double logic where the same core function for each kmod tool will be called twice, once on MODULE_DIRECTORY path and another time on MODULE_ALTERNATIVE_DIRECTORY, we need to somehow catch the error and print it only if both calls on these two directories fail. Otherwise we risk to make kmod very confusing for the user because we might show an error first (MODULE_DIRECTORY missing), and then the fallback (MODULE_ALTERNATIVE_DIRECTORY) successfully does its job leaving command is successful. Signed-off-by: Emanuele Giuseppe Esposito --- tools/log.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/log.h b/tools/log.h index 72836be7..f1a91b12 100644 --- a/tools/log.h +++ b/tools/log.h @@ -21,3 +21,36 @@ void log_printf(int prio, const char *fmt, ...) _printf_format_(2, 3); struct kmod_ctx; void log_setup_kmod_log(struct kmod_ctx *ctx, int priority); + +#define LOG_PTR_INIT(name) static char *name = NULL; + +/* SET_LOG_PTR: try to allocate the error message into a string pointed by + * msg_ptr, but if it fails it will just print it as ERR(). + * msg_ptr must be defined by the caller and initialized to NULL */ +#define SET_LOG_PTR(msg_ptr, ...) \ + do { \ + if (msg_ptr) \ + free(msg_ptr); \ + if (asprintf(&msg_ptr, __VA_ARGS__) < 0) \ + ERR(__VA_ARGS__); \ + } while (0); + +static inline char *pop_log_str(char **msg_ptr) +{ + char *ret = *msg_ptr; + *msg_ptr = NULL; + return ret; +} + +#define PRINT_LOG_PTR(prio, module_dir, module_alt_dir) \ + do { \ + if (module_dir) { \ + log_printf(prio, "%s", module_dir); \ + if (module_alt_dir && \ + strcmp(module_dir, module_alt_dir) != 0) { \ + log_printf(prio, "%s", module_alt_dir); \ + free(module_alt_dir); \ + } \ + free(module_dir); \ + } \ + } while (0); From 977c13ee9303abf97a8652502d4422bdfa499df8 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:11:58 -0500 Subject: [PATCH 04/32] tools: improve error logs to specify in which dirname is the module missing Currently if no module is found in MODULE_DIRECTORY, kmod will just print "Module %s not found", but now that we are adding two search paths, it is worth specifying which is the path that was not found. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modinfo.c | 12 ++++++++---- tools/modprobe.c | 8 +++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index 6f8147ea..ea4f08c2 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -265,7 +265,8 @@ static int modinfo_path_do(struct kmod_ctx *ctx, const char *path) struct kmod_module *mod; int err = kmod_module_new_from_path(ctx, path, &mod); if (err < 0) { - ERR("Module file %s not found.\n", path); + ERR("Module file %s not found in %s.\n", path, + kmod_get_dirname(ctx)); return err; } err = modinfo_do(mod); @@ -280,7 +281,8 @@ static int modinfo_name_do(struct kmod_ctx *ctx, const char *name) err = kmod_module_new_from_name_lookup(ctx, name, &mod); if (err < 0 || mod == NULL) { - ERR("Module name %s not found.\n", name); + ERR("Module name %s not found in %s.\n", name, + kmod_get_dirname(ctx)); return err < 0 ? err : -ENOENT; } @@ -295,12 +297,14 @@ static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias) struct kmod_list *l, *list = NULL; int err = kmod_module_new_from_lookup(ctx, alias, &list); if (err < 0) { - ERR("Module alias %s not found.\n", alias); + ERR("Module alias %s not found in %s.\n", alias, + kmod_get_dirname(ctx)); return err; } if (list == NULL) { - ERR("Module %s not found.\n", alias); + ERR("Module %s not found in %s.\n", alias, + kmod_get_dirname(ctx)); return -ENOENT; } diff --git a/tools/modprobe.c b/tools/modprobe.c index ec66e6fc..e5907e5c 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -210,7 +210,8 @@ static int show_modversions(struct kmod_ctx *ctx, const char *filename) struct kmod_module *mod; int err = kmod_module_new_from_path(ctx, filename, &mod); if (err < 0) { - LOG("Module %s not found.\n", filename); + LOG("Module %s not found in %s.\n", filename, + kmod_get_dirname(ctx)); return err; } @@ -237,7 +238,8 @@ static int show_exports(struct kmod_ctx *ctx, const char *filename) struct kmod_module *mod; int err = kmod_module_new_from_path(ctx, filename, &mod); if (err < 0) { - LOG("Module %s not found.\n", filename); + LOG("Module %s not found in %s.\n", filename, + kmod_get_dirname(ctx)); return err; } @@ -500,7 +502,7 @@ static int rmmod(struct kmod_ctx *ctx, const char *alias) return err; if (list == NULL) { - LOG("Module %s not found.\n", alias); + LOG("Module %s not found in %s.\n", alias, kmod_get_dirname(ctx)); err = -ENOENT; } From 32e21dcaeea49622a51121020f0dc127cae39fef Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 06:14:08 -0500 Subject: [PATCH 05/32] tools/kmod: use log.h log functions instead of fprintf Signed-off-by: Emanuele Giuseppe Esposito --- tools/static-nodes.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/tools/static-nodes.c b/tools/static-nodes.c index 0ecb9030..030630e7 100644 --- a/tools/static-nodes.c +++ b/tools/static-nodes.c @@ -202,26 +202,22 @@ static int do_static_nodes(int argc, char *argv[]) r = snprintf(modules, sizeof(modules), MODULE_DIRECTORY "/%s/modules.devname", kernel.release); if (r >= (int)sizeof(modules)) { - fprintf(stderr, - "Error: could not open " MODULE_DIRECTORY - "/%s/modules.devname - path too long\n", - kernel.release); + ERR("could not open " MODULE_DIRECTORY + "/%s/modules.devname - path too long\n", kernel.release); ret = EXIT_FAILURE; goto finish; } in = fopen(modules, "re"); if (in == NULL) { if (errno == ENOENT) { - fprintf(stderr, - "Warning: " MODULE_DIRECTORY - "/%s/modules.devname not found - ignoring\n", - kernel.release); + WRN(MODULE_DIRECTORY + "/%s/modules.devname not found - ignoring\n", + kernel.release); ret = EXIT_SUCCESS; } else { - fprintf(stderr, - "Error: could not open " MODULE_DIRECTORY - "/%s/modules.devname - %m\n", - kernel.release); + ERR("could not open " MODULE_DIRECTORY + "/%s/modules.devname - %m\n", + kernel.release); ret = EXIT_FAILURE; } goto finish; @@ -229,7 +225,7 @@ static int do_static_nodes(int argc, char *argv[]) r = mkdir_parents(output, 0755); if (r < 0) { - fprintf(stderr, "Error: could not create parent directory for %s - %m.\n", + ERR("could not create parent directory for %s - %m.\n", output); ret = EXIT_FAILURE; goto finish; @@ -237,7 +233,7 @@ static int do_static_nodes(int argc, char *argv[]) out = fopen(output, "we"); if (out == NULL) { - fprintf(stderr, "Error: could not create %s - %m\n", output); + ERR("could not create %s - %m\n", output); ret = EXIT_FAILURE; goto finish; } @@ -255,7 +251,7 @@ static int do_static_nodes(int argc, char *argv[]) matches = sscanf(buf, "%s %s %c%u:%u", modname, devname, &type, &maj, &min); if (matches != 5 || (type != 'c' && type != 'b')) { - fprintf(stderr, "Error: invalid devname entry: %s", buf); + ERR("invalid devname entry: %s", buf); ret = EXIT_FAILURE; continue; } From 93e9285436fac7c869dc7ddb32b95e4882e00d08 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:45:19 -0500 Subject: [PATCH 06/32] tools/static-nodes: move main logic into helpers Move code in do_static_nodes into two helpers: one to get the dirname (MODULE_DIRECTORY/$kernel) and another to do the main logic. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/static-nodes.c | 121 +++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 51 deletions(-) diff --git a/tools/static-nodes.c b/tools/static-nodes.c index 030630e7..ff4eed19 100644 --- a/tools/static-nodes.c +++ b/tools/static-nodes.c @@ -141,12 +141,74 @@ static void help(void) } } +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *module_directory, + const char *kversion) +{ + int n; + + n = snprintf(dirname_buf, dirname_size, + "%s/%s/modules.devname", module_directory, kversion); + if (n >= (int)dirname_size) { + ERR("could not open %s/%s/modules.devname: path too long\n", + module_directory, kversion); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int _do_static_nodes(char *modules, const char *path, char *kver, + const struct static_nodes_format *format, FILE *out) +{ + char buf[PATH_MAX]; + FILE *in = NULL; + int ret = EXIT_SUCCESS; + + in = fopen(modules, "re"); + if (in == NULL) { + if (errno == ENOENT) { + WRN("%s/%s/modules.devname not found - ignoring\n", + path, kver); + } else { + ERR("could not open %s/%s/modules.devname - %m\n", + path, kver); + } + return EXIT_FAILURE; + } + + while (fgets(buf, sizeof(buf), in) != NULL) { + char modname[PATH_MAX]; + char devname[PATH_MAX]; + char type; + unsigned int maj, min; + int matches; + + if (buf[0] == '#') + continue; + + matches = + sscanf(buf, "%s %s %c%u:%u", modname, devname, &type, &maj, &min); + if (matches != 5 || (type != 'c' && type != 'b')) { + ERR("invalid devname entry: %s", buf); + ret = EXIT_FAILURE; + continue; + } + + format->write(out, modname, devname, type, maj, min); + } + + fclose(in); + + return ret; +} + static int do_static_nodes(int argc, char *argv[]) { struct utsname kernel; - char modules[PATH_MAX], buf[PATH_MAX]; + char modules[PATH_MAX]; const char *output = "/dev/stdout"; - FILE *in = NULL, *out = NULL; + FILE *out = NULL; const struct static_nodes_format *format = &static_nodes_format_human; int r, ret = EXIT_SUCCESS; @@ -199,38 +261,12 @@ static int do_static_nodes(int argc, char *argv[]) goto finish; } - r = snprintf(modules, sizeof(modules), MODULE_DIRECTORY "/%s/modules.devname", - kernel.release); - if (r >= (int)sizeof(modules)) { - ERR("could not open " MODULE_DIRECTORY - "/%s/modules.devname - path too long\n", kernel.release); - ret = EXIT_FAILURE; - goto finish; - } - in = fopen(modules, "re"); - if (in == NULL) { - if (errno == ENOENT) { - WRN(MODULE_DIRECTORY - "/%s/modules.devname not found - ignoring\n", - kernel.release); - ret = EXIT_SUCCESS; - } else { - ERR("could not open " MODULE_DIRECTORY - "/%s/modules.devname - %m\n", - kernel.release); - ret = EXIT_FAILURE; - } - goto finish; - } - r = mkdir_parents(output, 0755); if (r < 0) { ERR("could not create parent directory for %s - %m.\n", output); ret = EXIT_FAILURE; - goto finish; } - out = fopen(output, "we"); if (out == NULL) { ERR("could not create %s - %m\n", output); @@ -238,30 +274,13 @@ static int do_static_nodes(int argc, char *argv[]) goto finish; } - while (fgets(buf, sizeof(buf), in) != NULL) { - char modname[PATH_MAX]; - char devname[PATH_MAX]; - char type; - unsigned int maj, min; - int matches; - - if (buf[0] == '#') - continue; - - matches = - sscanf(buf, "%s %s %c%u:%u", modname, devname, &type, &maj, &min); - if (matches != 5 || (type != 'c' && type != 'b')) { - ERR("invalid devname entry: %s", buf); - ret = EXIT_FAILURE; - continue; - } - - format->write(out, modname, devname, type, maj, min); - } - + ret = get_module_dirname(modules, sizeof(modules), MODULE_DIRECTORY, + kernel.release); + if (ret) + goto finish; + ret = _do_static_nodes(modules, MODULE_DIRECTORY, kernel.release, + format, out); finish: - if (in) - fclose(in); if (out) fclose(out); return ret; From 544ec40430621880e20723ddab2f970efcb54c33 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:47:21 -0500 Subject: [PATCH 07/32] tools/static-nodes: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/static-nodes.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/static-nodes.c b/tools/static-nodes.c index ff4eed19..47067a03 100644 --- a/tools/static-nodes.c +++ b/tools/static-nodes.c @@ -274,12 +274,20 @@ static int do_static_nodes(int argc, char *argv[]) goto finish; } + /* Try first with MODULE_DIRECTORY */ ret = get_module_dirname(modules, sizeof(modules), MODULE_DIRECTORY, kernel.release); - if (ret) - goto finish; - ret = _do_static_nodes(modules, MODULE_DIRECTORY, kernel.release, - format, out); + if (!ret) + ret = _do_static_nodes(modules, MODULE_DIRECTORY, kernel.release, + format, out); + + /* Whether MODULE_DIRECTORY went well or not, look at + * MODULE_ALTERNATIVE_DIRECTORY */ + ret = get_module_dirname(modules, sizeof(modules), + MODULE_ALTERNATIVE_DIRECTORY, kernel.release); + if (!ret) + ret = _do_static_nodes(modules, MODULE_ALTERNATIVE_DIRECTORY, + kernel.release, format, out); finish: if (out) fclose(out); From 86c5677c9248a1503982cb1ebece84c93d944fc8 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 06:59:22 -0500 Subject: [PATCH 08/32] tools/static-nodes: perform alternative directory lookup only if e nabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/static-nodes.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/static-nodes.c b/tools/static-nodes.c index 47067a03..9c89d41c 100644 --- a/tools/static-nodes.c +++ b/tools/static-nodes.c @@ -281,6 +281,7 @@ static int do_static_nodes(int argc, char *argv[]) ret = _do_static_nodes(modules, MODULE_DIRECTORY, kernel.release, format, out); + #if ENABLE_ALTERNATIVE_DIR /* Whether MODULE_DIRECTORY went well or not, look at * MODULE_ALTERNATIVE_DIRECTORY */ ret = get_module_dirname(modules, sizeof(modules), @@ -288,6 +289,7 @@ static int do_static_nodes(int argc, char *argv[]) if (!ret) ret = _do_static_nodes(modules, MODULE_ALTERNATIVE_DIRECTORY, kernel.release, format, out); + #endif finish: if (out) fclose(out); From 311d1694ee4ef1b7a9bfef6226e80b7eb84cc1dc Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:55:33 -0500 Subject: [PATCH 09/32] tools/modinfo: move main logic into helpers Move code in do_modinfo into two helpers: one to get the dirname ($root/MODULE_DIRECTORY/$kernel) and another to do the main logic. The first helper, get_module_dirname(), is also always called to figure the dirname path and to avoid providing NULL to the kmod_new() API. This is because kmod_new() always defaults to MODULE_DIRECTORY when the dirname path is empty, and won't work when MODULE_ALTERNATIVE_DIRECTORY will be used. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modinfo.c | 108 ++++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index ea4f08c2..eeed05f1 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -368,16 +368,64 @@ static bool is_module_filename(const char *name) return false; } -static int do_modinfo(int argc, char *argv[]) +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *root, const char *module_directory, + const char *kversion) +{ + int n; + + n = snprintf(dirname_buf, dirname_size, + "%s%s/%s", root, module_directory, kversion); + if (n >= (int)dirname_size) { + ERR("bad directory %s%s/%s: path too long\n", + root, module_directory, kversion); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int _do_modinfo(const char *dirname, int argc, char *argv[], + bool arg_is_modname) { struct kmod_ctx *ctx; + const char *null_config = NULL; + int i, err; + + ctx = kmod_new(dirname, &null_config); + if (!ctx) { + ERR("kmod_new() failed!\n"); + return EXIT_FAILURE; + } + + err = EXIT_SUCCESS; + for (i = optind; i < argc; i++) { + const char *name = argv[i]; + int r; + + if (arg_is_modname) + r = modinfo_name_do(ctx, name); + else if (is_module_filename(name)) + r = modinfo_path_do(ctx, name); + else + r = modinfo_alias_do(ctx, name); + + if (r < 0) + err = r; + } + + kmod_unref(ctx); + return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int do_modinfo(int argc, char *argv[]) +{ char dirname_buf[PATH_MAX]; - const char *dirname = NULL; const char *kversion = NULL; const char *root = NULL; - const char *null_config = NULL; bool arg_is_modname = false; - int i, err; + struct utsname u; + int err; for (;;) { int c, idx = 0; @@ -434,53 +482,23 @@ static int do_modinfo(int argc, char *argv[]) return EXIT_FAILURE; } - if (root != NULL || kversion != NULL) { - struct utsname u; - int n; - if (root == NULL) - root = ""; - if (kversion == NULL) { - if (uname(&u) < 0) { - ERR("uname() failed: %m\n"); - return EXIT_FAILURE; - } - kversion = u.release; - } - - n = snprintf(dirname_buf, sizeof(dirname_buf), - "%s" MODULE_DIRECTORY "/%s", root, kversion); - if (n >= (int)sizeof(dirname_buf)) { - ERR("bad directory %s" MODULE_DIRECTORY "/%s: path too long\n", - root, kversion); + if (root == NULL) + root = ""; + if (kversion == NULL){ + if (uname(&u) < 0) { + ERR("uname() failed: %m\n"); return EXIT_FAILURE; } - dirname = dirname_buf; + kversion = u.release; } - ctx = kmod_new(dirname, &null_config); - if (!ctx) { - ERR("kmod_new() failed!\n"); + err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, + MODULE_DIRECTORY, kversion); + if (err) return EXIT_FAILURE; - } - - err = 0; - for (i = optind; i < argc; i++) { - const char *name = argv[i]; - int r; - - if (arg_is_modname) - r = modinfo_name_do(ctx, name); - else if (is_module_filename(name)) - r = modinfo_path_do(ctx, name); - else - r = modinfo_alias_do(ctx, name); - - if (r < 0) - err = r; - } + err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); - kmod_unref(ctx); - return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return err; } const struct kmod_cmd kmod_cmd_compat_modinfo = { From a16a5ba85e660e5703d6be5811e2420567c760e9 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:56:37 -0500 Subject: [PATCH 10/32] tools/modinfo: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modinfo.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index eeed05f1..d3ab988d 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -492,13 +492,22 @@ static int do_modinfo(int argc, char *argv[]) kversion = u.release; } + /* Try first with MODULE_DIRECTORY */ err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, MODULE_DIRECTORY, kversion); - if (err) - return EXIT_FAILURE; - err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); + if (!err) + err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); + if (!err) + /* MODULE_DIRECTORY was succesful */ + return EXIT_SUCCESS; - return err; + /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ + err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, + MODULE_ALTERNATIVE_DIRECTORY, kversion); + if (!err) + err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); + + return err ? EXIT_FAILURE : EXIT_SUCCESS; } const struct kmod_cmd kmod_cmd_compat_modinfo = { From b4653cf2ac1969397c886e6768f2f1c0d9f2e680 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 04:46:03 -0500 Subject: [PATCH 11/32] tools/modinfo: perform alternative directory lookup only if enabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/modinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/modinfo.c b/tools/modinfo.c index d3ab988d..51a01338 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -501,11 +501,13 @@ static int do_modinfo(int argc, char *argv[]) /* MODULE_DIRECTORY was succesful */ return EXIT_SUCCESS; + #if ENABLE_ALTERNATIVE_DIR /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, MODULE_ALTERNATIVE_DIRECTORY, kversion); if (!err) err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); + #endif return err ? EXIT_FAILURE : EXIT_SUCCESS; } From 7609ec90a5e0f3cffdabbafc08b84c65d4a227bb Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 05:20:55 -0500 Subject: [PATCH 12/32] tools/modinfo: avoid redundant log messages -- can be squashed Using the macros developed in log.h, catch the error and print it only if both MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY call fail. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modinfo.c | 53 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/tools/modinfo.c b/tools/modinfo.c index 51a01338..3536e9e9 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -24,6 +24,9 @@ static char separator = '\n'; static const char *field = NULL; +LOG_PTR_INIT(error_log) +#define SET_ERR(...) SET_LOG_PTR(error_log, __VA_ARGS__) + struct param { struct param *next; const char *name; @@ -84,7 +87,7 @@ static int process_parm(const char *key, const char *value, struct param **param struct param *it; const char *colon = strchr(value, ':'); if (colon == NULL) { - ERR("Found invalid \"%s=%s\": missing ':'\n", key, value); + SET_ERR("Found invalid \"%s=%s\": missing ':'\n", key, value); return 0; } @@ -104,7 +107,7 @@ static int process_parm(const char *key, const char *value, struct param **param it = add_param(name, namelen, param, paramlen, type, typelen, params); if (it == NULL) { - ERR("Unable to add parameter: %m\n"); + SET_ERR("Unable to add parameter: %m\n"); return -ENOMEM; } @@ -188,8 +191,8 @@ static int modinfo_do(struct kmod_module *mod) */ return 0; } - ERR("could not get modinfo from '%s': %s\n", kmod_module_get_name(mod), - strerror(-err)); + SET_ERR("could not get modinfo from '%s': %s\n", + kmod_module_get_name(mod), strerror(-err)); return err; } @@ -265,8 +268,8 @@ static int modinfo_path_do(struct kmod_ctx *ctx, const char *path) struct kmod_module *mod; int err = kmod_module_new_from_path(ctx, path, &mod); if (err < 0) { - ERR("Module file %s not found in %s.\n", path, - kmod_get_dirname(ctx)); + SET_ERR("Module file %s not found in %s.\n", path, + kmod_get_dirname(ctx)); return err; } err = modinfo_do(mod); @@ -281,8 +284,8 @@ static int modinfo_name_do(struct kmod_ctx *ctx, const char *name) err = kmod_module_new_from_name_lookup(ctx, name, &mod); if (err < 0 || mod == NULL) { - ERR("Module name %s not found in %s.\n", name, - kmod_get_dirname(ctx)); + SET_ERR("Module name %s not found in %s.\n", name, + kmod_get_dirname(ctx)); return err < 0 ? err : -ENOENT; } @@ -297,14 +300,14 @@ static int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias) struct kmod_list *l, *list = NULL; int err = kmod_module_new_from_lookup(ctx, alias, &list); if (err < 0) { - ERR("Module alias %s not found in %s.\n", alias, - kmod_get_dirname(ctx)); + SET_ERR("Module alias %s not found in %s.\n", alias, + kmod_get_dirname(ctx)); return err; } if (list == NULL) { - ERR("Module %s not found in %s.\n", alias, - kmod_get_dirname(ctx)); + SET_ERR("Module %s not found in %s.\n", alias, + kmod_get_dirname(ctx)); return -ENOENT; } @@ -377,8 +380,8 @@ static int get_module_dirname(char *dirname_buf, size_t dirname_size, n = snprintf(dirname_buf, dirname_size, "%s%s/%s", root, module_directory, kversion); if (n >= (int)dirname_size) { - ERR("bad directory %s%s/%s: path too long\n", - root, module_directory, kversion); + SET_ERR("bad directory %s%s/%s: path too long\n", root, + module_directory, kversion); return EXIT_FAILURE; } @@ -394,7 +397,7 @@ static int _do_modinfo(const char *dirname, int argc, char *argv[], ctx = kmod_new(dirname, &null_config); if (!ctx) { - ERR("kmod_new() failed!\n"); + SET_ERR("kmod_new() failed!\n"); return EXIT_FAILURE; } @@ -424,6 +427,8 @@ static int do_modinfo(int argc, char *argv[]) const char *kversion = NULL; const char *root = NULL; bool arg_is_modname = false; + char *module_dir_error = NULL; + char *module_alt_dir_error = NULL; struct utsname u; int err; @@ -497,7 +502,12 @@ static int do_modinfo(int argc, char *argv[]) MODULE_DIRECTORY, kversion); if (!err) err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); - if (!err) + + if (err) + /* Store the error and print it *if* + * MODULE_ALTERNATIVE_DIRECTORY fails too */ + module_dir_error = pop_log_str(&error_log); + else /* MODULE_DIRECTORY was succesful */ return EXIT_SUCCESS; @@ -507,8 +517,19 @@ static int do_modinfo(int argc, char *argv[]) MODULE_ALTERNATIVE_DIRECTORY, kversion); if (!err) err = _do_modinfo(dirname_buf, argc, argv, arg_is_modname); + + if (err) + /* Store the error and print it after MODULE_DIRECTORY */ + module_alt_dir_error = pop_log_str(&error_log); + else { + /* MODULE_ALTERNATIVE_DIRECTORY was succesful, no need to print + * module_dir_error */ + free(module_dir_error); + module_dir_error = NULL; + } #endif + PRINT_LOG_PTR(LOG_ERR, module_dir_error, module_alt_dir_error); return err ? EXIT_FAILURE : EXIT_SUCCESS; } From ba3b642484398a3f1480d9b7823b6c12c2648c16 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Tue, 28 Jan 2025 10:38:02 -0500 Subject: [PATCH 13/32] testsuite/modinfo: test MODULE_ALTERNATIVE_DIRECTORY Signed-off-by: Emanuele Giuseppe Esposito --- .../test-modinfo/builtin/run/modules/6.11.0 | 1 + .../test-modinfo/external/run/modules/4.4.4 | 1 + testsuite/test-modinfo.c | 45 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 120000 testsuite/rootfs-pristine/test-modinfo/builtin/run/modules/6.11.0 create mode 120000 testsuite/rootfs-pristine/test-modinfo/external/run/modules/4.4.4 diff --git a/testsuite/rootfs-pristine/test-modinfo/builtin/run/modules/6.11.0 b/testsuite/rootfs-pristine/test-modinfo/builtin/run/modules/6.11.0 new file mode 120000 index 00000000..7baa5694 --- /dev/null +++ b/testsuite/rootfs-pristine/test-modinfo/builtin/run/modules/6.11.0 @@ -0,0 +1 @@ +../../../external/lib/modules/4.4.4 \ No newline at end of file diff --git a/testsuite/rootfs-pristine/test-modinfo/external/run/modules/4.4.4 b/testsuite/rootfs-pristine/test-modinfo/external/run/modules/4.4.4 new file mode 120000 index 00000000..206db607 --- /dev/null +++ b/testsuite/rootfs-pristine/test-modinfo/external/run/modules/4.4.4 @@ -0,0 +1 @@ +../../../builtin/lib/modules/6.11.0 \ No newline at end of file diff --git a/testsuite/test-modinfo.c b/testsuite/test-modinfo.c index b936e2fa..c3e79acb 100644 --- a/testsuite/test-modinfo.c +++ b/testsuite/test-modinfo.c @@ -124,4 +124,49 @@ DEFINE_TEST(test_modinfo_builtin, .out = TESTSUITE_ROOTFS "test-modinfo/correct-builtin.txt", }); +static noreturn int test_modinfo_alternative(const struct test *t) +{ + const char *const args[] = { + // clang-format off + progname, + "-F", "filename", + "mod-simple", + NULL, + // clang-format on + }; + test_spawn_prog(progname, args); + exit(EXIT_FAILURE); +} +DEFINE_TEST(test_modinfo_alternative, + .description = "check if modinfo finds module in alternative directory", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/builtin", + [TC_UNAME_R] = "6.11.0", + }, + .output = { + .out = TESTSUITE_ROOTFS "test-modinfo/correct-external.txt", + }); + +static noreturn int test_modinfo_alternative_inv(const struct test *t) +{ + const char *const args[] = { + // clang-format off + progname, + "intel_uncore", + NULL, + // clang-format on + }; + test_spawn_prog(progname, args); + exit(EXIT_FAILURE); +} +DEFINE_TEST(test_modinfo_alternative_inv, + .description = "check if modinfo finds module in alternative directory", + .config = { + [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/external", + [TC_UNAME_R] = "4.4.4", + }, + .output = { + .out = TESTSUITE_ROOTFS "test-modinfo/correct-builtin.txt", + }); + TESTSUITE_MAIN(); From 668277a9c36a7022cadded830696228bc55be9db Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 10:12:39 -0500 Subject: [PATCH 14/32] tools/modprobe: reduce LOG level otherwise it exits failure immediately Now that we have to repeat the same logic twice for MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY, setting LOG priority to FATAL causes modprobe to exit failure, without trying the second path. Therefore increase the log priority to ERROR. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modprobe.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index e5907e5c..9d213693 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -27,7 +27,13 @@ #include "kmod.h" -static int log_priority = LOG_CRIT; +/* + * Do NOT increase priority higher than LOG_ERR, because the main logic is + * called twice and if the first time it errors (expected), the log function + * will call exit(EXIT_FAILURE) and the second call to the main function will + * not be executed. + */ +static int log_priority = LOG_ERR; static int use_syslog = 0; #define LOG(...) log_printf(log_priority, __VA_ARGS__) From ace85d1b54281af05d21de7c22412dab3aa2e4d8 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:02:25 -0500 Subject: [PATCH 15/32] tools/modprobe: move main logic into helpers Move code in do_modprobe into two helpers: one to get the dirname ($root/MODULE_DIRECTORY/$kernel) and another to do the main logic. The first helper, get_module_dirname(), is also always called to figure the dirname path and to avoid providing NULL to the kmod_new() API. This is because kmod_new() always defaults to MODULE_DIRECTORY when the dirname path is empty, and won't work when MODULE_ALTERNATIVE_DIRECTORY will be used. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modprobe.c | 124 +++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 9d213693..020e3494 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -756,14 +756,70 @@ static char **prepend_options_from_env(int *p_argc, char **orig_argv) return new_argv; } -static int do_modprobe(int argc, char **orig_argv) +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *root, const char *module_directory, + const char *kversion) +{ + int n; + + n = snprintf(dirname_buf, dirname_size, + "%s%s/%s", root, module_directory, kversion); + if (n >= (int)dirname_size) { + ERR("bad directory %s%s/%s: path too long\n", + root, module_directory, kversion); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int _do_modprobe(const char *dirname, const char **config_paths, + char **args, int nargs, int do_show_config, + int do_show_modversions, int do_show_exports, + int do_remove, int use_all) { struct kmod_ctx *ctx; + int err; + + ctx = kmod_new(dirname, config_paths); + if (!ctx) { + ERR("kmod_new() failed!\n"); + return EXIT_FAILURE; + } + + log_setup_kmod_log(ctx, verbose); + + kmod_load_resources(ctx); + + if (do_show_config) + err = show_config(ctx); + else if (do_show_modversions) + err = show_modversions(ctx, args[0]); + else if (do_show_exports) + err = show_exports(ctx, args[0]); + else if (do_remove) + err = rmmod_all(ctx, args, nargs); + else if (use_all) + err = insmod_all(ctx, args, nargs); + else { + char *opts; + err = options_from_array(args + 1, nargs - 1, &opts); + if (err == 0) { + err = insmod(ctx, args[0], opts); + free(opts); + } + } + + kmod_unref(ctx); + return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int do_modprobe(int argc, char **orig_argv) +{ char **args = NULL, **argv; const char **config_paths = NULL; int nargs = 0, n_config_paths = 0; char dirname_buf[PATH_MAX]; - const char *dirname = NULL; const char *root = NULL; const char *kversion = NULL; int use_all = 0; @@ -772,6 +828,7 @@ static int do_modprobe(int argc, char **orig_argv) int do_show_modversions = 0; int do_show_exports = 0; int err; + struct utsname u; struct stat stat_buf; argv = prepend_options_from_env(&argc, orig_argv); @@ -914,61 +971,24 @@ static int do_modprobe(int argc, char **orig_argv) } } - if (root != NULL || kversion != NULL) { - struct utsname u; - int n; - if (root == NULL) - root = ""; - if (kversion == NULL) { - if (uname(&u) < 0) { - ERR("uname() failed: %m\n"); - err = -1; - goto done; - } - kversion = u.release; - } - n = snprintf(dirname_buf, sizeof(dirname_buf), - "%s" MODULE_DIRECTORY "/%s", root, kversion); - if (n >= (int)sizeof(dirname_buf)) { - ERR("bad directory %s" MODULE_DIRECTORY "/%s: path too long\n", - root, kversion); + if (root == NULL) + root = ""; + if (kversion == NULL) { + if (uname(&u) < 0) { + ERR("uname() failed: %m\n"); err = -1; goto done; } - dirname = dirname_buf; + kversion = u.release; } - ctx = kmod_new(dirname, config_paths); - if (!ctx) { - ERR("kmod_new() failed!\n"); - err = -1; + err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, + MODULE_DIRECTORY, kversion); + if (err) goto done; - } - - log_setup_kmod_log(ctx, verbose); - - kmod_load_resources(ctx); - - if (do_show_config) - err = show_config(ctx); - else if (do_show_modversions) - err = show_modversions(ctx, args[0]); - else if (do_show_exports) - err = show_exports(ctx, args[0]); - else if (do_remove) - err = rmmod_all(ctx, args, nargs); - else if (use_all) - err = insmod_all(ctx, args, nargs); - else { - char *opts; - err = options_from_array(args + 1, nargs - 1, &opts); - if (err == 0) { - err = insmod(ctx, args[0], opts); - free(opts); - } - } - - kmod_unref(ctx); + err = _do_modprobe(dirname_buf, config_paths, args, nargs, do_show_config, + do_show_modversions, do_show_exports, do_remove, + use_all); done: log_close(); @@ -978,7 +998,7 @@ static int do_modprobe(int argc, char **orig_argv) free(config_paths); - return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return err; } const struct kmod_cmd kmod_cmd_compat_modprobe = { From 288d0ca77a664400fd6853f85f08dda345575b01 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:03:12 -0500 Subject: [PATCH 16/32] tools/modprobe: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modprobe.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 020e3494..b55db6d4 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -982,13 +982,24 @@ static int do_modprobe(int argc, char **orig_argv) kversion = u.release; } + /* Try first with MODULE_DIRECTORY */ err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, MODULE_DIRECTORY, kversion); - if (err) + if (!err) + err = _do_modprobe(dirname_buf, config_paths, args, nargs, + do_show_config, do_show_modversions, + do_show_exports, do_remove, use_all); + if (!err) + /* MODULE_DIRECTORY was succesful */ goto done; - err = _do_modprobe(dirname_buf, config_paths, args, nargs, do_show_config, - do_show_modversions, do_show_exports, do_remove, - use_all); + + /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ + err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, + MODULE_ALTERNATIVE_DIRECTORY, kversion); + if (!err) + err = _do_modprobe(dirname_buf, config_paths, args, nargs, + do_show_config, do_show_modversions, + do_show_exports, do_remove, use_all); done: log_close(); From 0ab9b31ca2d5d32cc5907d99f56b986ecbd3456d Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 07:24:32 -0500 Subject: [PATCH 17/32] tools/modprobe: perform alternative directory lookup only if enabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/modprobe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/modprobe.c b/tools/modprobe.c index b55db6d4..2deaf927 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -993,6 +993,7 @@ static int do_modprobe(int argc, char **orig_argv) /* MODULE_DIRECTORY was succesful */ goto done; + #if ENABLE_ALTERNATIVE_DIR /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ err = get_module_dirname(dirname_buf, sizeof(dirname_buf), root, MODULE_ALTERNATIVE_DIRECTORY, kversion); @@ -1000,6 +1001,7 @@ static int do_modprobe(int argc, char **orig_argv) err = _do_modprobe(dirname_buf, config_paths, args, nargs, do_show_config, do_show_modversions, do_show_exports, do_remove, use_all); + #endif done: log_close(); From 26f18bff1384809af952ff07bf31ff6966a31c22 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 27 Jan 2025 12:05:47 -0500 Subject: [PATCH 18/32] tools/modprobe: avoid redundant log messages -- can be squashed Using the macros developed in log.h, catch the error and print it only if both MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY call fail. Signed-off-by: Emanuele Giuseppe Esposito --- tools/modprobe.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/modprobe.c b/tools/modprobe.c index 2deaf927..1404a472 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -35,7 +35,8 @@ */ static int log_priority = LOG_ERR; static int use_syslog = 0; -#define LOG(...) log_printf(log_priority, __VA_ARGS__) +LOG_PTR_INIT(error_log) +#define LOG(...) SET_LOG_PTR(error_log, __VA_ARGS__) #define DEFAULT_VERBOSE LOG_WARNING static int verbose = DEFAULT_VERBOSE; @@ -827,6 +828,8 @@ static int do_modprobe(int argc, char **orig_argv) int do_show_config = 0; int do_show_modversions = 0; int do_show_exports = 0; + char *module_dir_error = NULL; + char *module_alt_dir_error = NULL; int err; struct utsname u; struct stat stat_buf; @@ -989,7 +992,12 @@ static int do_modprobe(int argc, char **orig_argv) err = _do_modprobe(dirname_buf, config_paths, args, nargs, do_show_config, do_show_modversions, do_show_exports, do_remove, use_all); - if (!err) + + if (err) + /* Store the error and print it *if* + * MODULE_ALTERNATIVE_DIRECTORY fails too */ + module_dir_error = pop_log_str(&error_log); + else /* MODULE_DIRECTORY was succesful */ goto done; @@ -1001,9 +1009,20 @@ static int do_modprobe(int argc, char **orig_argv) err = _do_modprobe(dirname_buf, config_paths, args, nargs, do_show_config, do_show_modversions, do_show_exports, do_remove, use_all); + + if (err) + /* Store the error and print it after MODULE_DIRECTORY */ + module_alt_dir_error = pop_log_str(&error_log); + else { + /* MODULE_ALTERNATIVE_DIRECTORY was succesful, no need to print + * module_dir_error */ + free(module_dir_error); + module_dir_error = NULL; + } #endif done: + PRINT_LOG_PTR(log_priority, module_dir_error, module_alt_dir_error); log_close(); if (argv != orig_argv) From 54d28d0f732ce5173aaaba041d90b21a493407f9 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:09:12 -0500 Subject: [PATCH 19/32] tools/insmod: move main logic into helpers Move code in do_insmod into two helpers: one to get the dirname ($root/MODULE_DIRECTORY/$kernel) and another to do the main logic. The first helper, get_module_dirname(), is also always called to figure the dirname path and to avoid providing NULL to the kmod_new() API. This is because kmod_new() always defaults to MODULE_DIRECTORY when the dirname path is empty, and won't work when MODULE_ALTERNATIVE_DIRECTORY will be used. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/insmod.c | 83 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/tools/insmod.c b/tools/insmod.c index f7916b5f..f9f719e1 100644 --- a/tools/insmod.c +++ b/tools/insmod.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -58,16 +59,68 @@ static const char *mod_strerror(int err) } } -static int do_insmod(int argc, char *argv[]) +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *module_directory) +{ + struct utsname u; + int n; + + if (uname(&u) < 0) + return EXIT_FAILURE; + + n = snprintf(dirname_buf, dirname_size, "%s/%s", module_directory, + u.release); + if (n >= (int)dirname_size) { + ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int _do_insmod(const char *dirname, const char *filename, + unsigned int flags, char *opts, int verbose) { struct kmod_ctx *ctx = NULL; + const char *null_config = NULL; struct kmod_module *mod; + int r; + + ctx = kmod_new(dirname, &null_config); + if (!ctx) { + ERR("kmod_new() failed!\n"); + r = EXIT_FAILURE; + goto finish; + } + + log_setup_kmod_log(ctx, verbose); + + r = kmod_module_new_from_path(ctx, filename, &mod); + if (r < 0) { + ERR("could not load module %s: %s\n", filename, strerror(-r)); + goto finish; + } + + r = kmod_module_insert_module(mod, flags, opts); + if (r < 0) + ERR("could not insert module %s: %s\n", filename, mod_strerror(-r)); + + kmod_module_unref(mod); + +finish: + kmod_unref(ctx); + return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int do_insmod(int argc, char *argv[]) +{ const char *filename; + char dirname_buf[PATH_MAX]; char *opts = NULL; int verbose = LOG_ERR; int use_syslog = 0; int c, r = 0; - const char *null_config = NULL; unsigned int flags = 0; while ((c = getopt_long(argc, argv, cmdopts_s, cmdopts, NULL)) != -1) { @@ -115,33 +168,17 @@ static int do_insmod(int argc, char *argv[]) if (r < 0) goto end; - ctx = kmod_new(NULL, &null_config); - if (!ctx) { - ERR("kmod_new() failed!\n"); - r = EXIT_FAILURE; - goto end; - } - - log_setup_kmod_log(ctx, verbose); - - r = kmod_module_new_from_path(ctx, filename, &mod); - if (r < 0) { - ERR("could not load module %s: %s\n", filename, strerror(-r)); + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_DIRECTORY); + if (r) goto end; - } - - r = kmod_module_insert_module(mod, flags, opts); - if (r < 0) - ERR("could not insert module %s: %s\n", filename, mod_strerror(-r)); - - kmod_module_unref(mod); + r = _do_insmod(dirname_buf, filename, flags, opts, verbose); end: - kmod_unref(ctx); free(opts); log_close(); - return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return r; } const struct kmod_cmd kmod_cmd_compat_insmod = { From 7524a89cba8f4f3950b97a33badb6c977dd95223 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:10:02 -0500 Subject: [PATCH 20/32] tools/insmod: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/insmod.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/insmod.c b/tools/insmod.c index f9f719e1..526bfb9f 100644 --- a/tools/insmod.c +++ b/tools/insmod.c @@ -168,11 +168,20 @@ static int do_insmod(int argc, char *argv[]) if (r < 0) goto end; + /* Try first with MODULE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_DIRECTORY); - if (r) + if (!r) + r = _do_insmod(dirname_buf, filename, flags, opts, verbose); + if (!r) + /* MODULE_DIRECTORY was succesful */ goto end; - r = _do_insmod(dirname_buf, filename, flags, opts, verbose); + + /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_ALTERNATIVE_DIRECTORY); + if (!r) + r = _do_insmod(dirname_buf, filename, flags, opts, verbose); end: free(opts); From 34fb2d3a4135a92e2d6c203d7975b8b5da2ff758 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 07:46:34 -0500 Subject: [PATCH 21/32] tools/insmod: perform alternative directory lookup only if enabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/insmod.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/insmod.c b/tools/insmod.c index 526bfb9f..e2a6992f 100644 --- a/tools/insmod.c +++ b/tools/insmod.c @@ -177,11 +177,13 @@ static int do_insmod(int argc, char *argv[]) /* MODULE_DIRECTORY was succesful */ goto end; + #if ENABLE_ALTERNATIVE_DIR /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_insmod(dirname_buf, filename, flags, opts, verbose); + #endif end: free(opts); From 7647358d590e099743cfdd14f0b7a68b7674e908 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 07:56:10 -0500 Subject: [PATCH 22/32] tools/insmod: avoid redundant log messages -- can be squashed Using the macros developed in log.h, catch the error and print it only if both MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY call fail. Signed-off-by: Emanuele Giuseppe Esposito --- tools/insmod.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/tools/insmod.c b/tools/insmod.c index e2a6992f..ff65991d 100644 --- a/tools/insmod.c +++ b/tools/insmod.c @@ -17,6 +17,9 @@ #include "kmod.h" +LOG_PTR_INIT(error_log) +#define SET_ERR(...) SET_LOG_PTR(error_log, __VA_ARGS__) + static const char cmdopts_s[] = "fsvVh"; static const struct option cmdopts[] = { // clang-format off @@ -71,8 +74,8 @@ static int get_module_dirname(char *dirname_buf, size_t dirname_size, n = snprintf(dirname_buf, dirname_size, "%s/%s", module_directory, u.release); if (n >= (int)dirname_size) { - ERR("bad directory %s/%s: path too long\n", - module_directory, u.release); + SET_ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); return EXIT_FAILURE; } @@ -89,7 +92,7 @@ static int _do_insmod(const char *dirname, const char *filename, ctx = kmod_new(dirname, &null_config); if (!ctx) { - ERR("kmod_new() failed!\n"); + SET_ERR("kmod_new() failed!\n"); r = EXIT_FAILURE; goto finish; } @@ -98,13 +101,13 @@ static int _do_insmod(const char *dirname, const char *filename, r = kmod_module_new_from_path(ctx, filename, &mod); if (r < 0) { - ERR("could not load module %s: %s\n", filename, strerror(-r)); + SET_ERR("could not load module %s: %s\n", filename, strerror(-r)); goto finish; } r = kmod_module_insert_module(mod, flags, opts); if (r < 0) - ERR("could not insert module %s: %s\n", filename, mod_strerror(-r)); + SET_ERR("could not insert module %s: %s\n", filename, mod_strerror(-r)); kmod_module_unref(mod); @@ -118,6 +121,8 @@ static int do_insmod(int argc, char *argv[]) const char *filename; char dirname_buf[PATH_MAX]; char *opts = NULL; + char *module_dir_error = NULL; + char *module_alt_dir_error = NULL; int verbose = LOG_ERR; int use_syslog = 0; int c, r = 0; @@ -173,7 +178,12 @@ static int do_insmod(int argc, char *argv[]) MODULE_DIRECTORY); if (!r) r = _do_insmod(dirname_buf, filename, flags, opts, verbose); - if (!r) + + if (r) + /* Store the error and print it *if* + * MODULE_ALTERNATIVE_DIRECTORY fails too */ + module_dir_error = pop_log_str(&error_log); + else /* MODULE_DIRECTORY was succesful */ goto end; @@ -183,8 +193,19 @@ static int do_insmod(int argc, char *argv[]) MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_insmod(dirname_buf, filename, flags, opts, verbose); + + if (r) + /* Store the error and print it after MODULE_DIRECTORY */ + module_alt_dir_error = pop_log_str(&error_log); + else { + /* MODULE_ALTERNATIVE_DIRECTORY was succesful, no need to print + * module_dir_error */ + free(module_dir_error); + module_dir_error = NULL; + } #endif + PRINT_LOG_PTR(LOG_ERR, module_dir_error, module_alt_dir_error); end: free(opts); From ae640717a21ca960c1c05d6c4004d2b3bcb6dd6b Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:13:21 -0500 Subject: [PATCH 23/32] tools/lsmod: move main logic into helpers Move code in do_lsmod into two helpers: one to get the dirname ($root/MODULE_DIRECTORY/$kernel) and another to do the main logic. The first helper, get_module_dirname(), is also always called to figure the dirname path and to avoid providing NULL to the kmod_new() API. This is because kmod_new() always defaults to MODULE_DIRECTORY when the dirname path is empty, and won't work when MODULE_ALTERNATIVE_DIRECTORY will be used. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/lsmod.c | 116 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 39 deletions(-) diff --git a/tools/lsmod.c b/tools/lsmod.c index ea68d1dc..8b806a28 100644 --- a/tools/lsmod.c +++ b/tools/lsmod.c @@ -10,6 +10,9 @@ #include #include #include +#include + +#include #include @@ -38,50 +41,38 @@ static void help(void) program_invocation_short_name); } -static int do_lsmod(int argc, char *argv[]) +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *module_directory) { - struct kmod_ctx *ctx = NULL; - const char *null_config = NULL; - struct kmod_list *list, *itr; - int verbose = LOG_ERR; - int use_syslog = 0; - int err, c, r = 0; - - while ((c = getopt_long(argc, argv, cmdopts_s, cmdopts, NULL)) != -1) { - switch (c) { - case 's': - use_syslog = 1; - break; - case 'v': - verbose++; - break; - case 'h': - help(); - return EXIT_SUCCESS; - case 'V': - kmod_version(); - return EXIT_SUCCESS; - case '?': - return EXIT_FAILURE; - default: - ERR("unexpected getopt_long() value '%c'.\n", c); - return EXIT_FAILURE; - } + struct utsname u; + int n; + + if (uname(&u) < 0) + return EXIT_FAILURE; + + n = snprintf(dirname_buf, dirname_size, + "%s/%s", module_directory, u.release); + if (n >= (int)dirname_size) { + ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); + return EXIT_FAILURE; } - log_open(use_syslog); + return EXIT_SUCCESS; +} - if (optind < argc) { - ERR("too many arguments provided.\n"); - r = EXIT_FAILURE; - goto done; - } +static int _do_lsmod(const char *dirname, int verbose) +{ + struct kmod_ctx *ctx = NULL; + const char *null_config = NULL; + struct kmod_list *list, *itr; + int r, err; - ctx = kmod_new(NULL, &null_config); + ctx = kmod_new(dirname, &null_config); if (!ctx) { ERR("kmod_new() failed!\n"); r = EXIT_FAILURE; - goto done; + goto finish; } log_setup_kmod_log(ctx, verbose); @@ -90,7 +81,7 @@ static int do_lsmod(int argc, char *argv[]) if (err < 0) { ERR("could not get list of modules: %s\n", strerror(-err)); r = EXIT_FAILURE; - goto done; + goto finish; } puts("Module Size Used by"); @@ -120,11 +111,58 @@ static int do_lsmod(int argc, char *argv[]) } kmod_module_unref_list(list); -done: +finish: kmod_unref(ctx); + return r; +} + +static int do_lsmod(int argc, char *argv[]) +{ + char dirname_buf[PATH_MAX]; + int verbose = LOG_ERR; + int use_syslog = 0; + int c, r = 0; + + while ((c = getopt_long(argc, argv, cmdopts_s, cmdopts, NULL)) != -1) { + switch (c) { + case 's': + use_syslog = 1; + break; + case 'v': + verbose++; + break; + case 'h': + help(); + return EXIT_SUCCESS; + case 'V': + kmod_version(); + return EXIT_SUCCESS; + case '?': + return EXIT_FAILURE; + default: + ERR("unexpected getopt_long() value '%c'.\n", c); + return EXIT_FAILURE; + } + } + + log_open(use_syslog); + + if (optind < argc) { + ERR("too many arguments provided.\n"); + r = EXIT_FAILURE; + goto done; + } + + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_DIRECTORY); + if (r) + goto done; + r = _do_lsmod(dirname_buf, verbose); + +done: log_close(); - return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return r; } const struct kmod_cmd kmod_cmd_compat_lsmod = { From 8ebaf6eb06fffdac0432a074edddbcf8a9a05ef2 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:14:23 -0500 Subject: [PATCH 24/32] tools/lsmod: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/lsmod.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/lsmod.c b/tools/lsmod.c index 8b806a28..8a9e4be1 100644 --- a/tools/lsmod.c +++ b/tools/lsmod.c @@ -153,11 +153,20 @@ static int do_lsmod(int argc, char *argv[]) goto done; } + /* Try first with MODULE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_DIRECTORY); - if (r) + if (!r) + r = _do_lsmod(dirname_buf, verbose); + if (!r) + /* MODULE_DIRECTORY was succesful */ goto done; - r = _do_lsmod(dirname_buf, verbose); + + /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_ALTERNATIVE_DIRECTORY); + if (!r) + r = _do_lsmod(dirname_buf, verbose); done: log_close(); From 19430f9e1e729b8a5d0e1031e873da42221058dc Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 08:04:21 -0500 Subject: [PATCH 25/32] tools/lsmod: perform alternative directory lookup only if enabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/lsmod.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/lsmod.c b/tools/lsmod.c index 8a9e4be1..6e1e4edf 100644 --- a/tools/lsmod.c +++ b/tools/lsmod.c @@ -162,11 +162,13 @@ static int do_lsmod(int argc, char *argv[]) /* MODULE_DIRECTORY was succesful */ goto done; + #if ENABLE_ALTERNATIVE_DIR /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_lsmod(dirname_buf, verbose); + #endif done: log_close(); From 0ad9d9a5ff8ff25956173faaa1942a0319bfea36 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 08:08:14 -0500 Subject: [PATCH 26/32] tools/lsmod: avoid redundant log messages -- can be squashed Using the macros developed in log.h, catch the error and print it only if both MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY call fail. Signed-off-by: Emanuele Giuseppe Esposito --- tools/lsmod.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/tools/lsmod.c b/tools/lsmod.c index 6e1e4edf..c8213cd6 100644 --- a/tools/lsmod.c +++ b/tools/lsmod.c @@ -18,6 +18,9 @@ #include "kmod.h" +LOG_PTR_INIT(error_log) +#define SET_ERR(...) SET_LOG_PTR(error_log, __VA_ARGS__) + static const char cmdopts_s[] = "svVh"; static const struct option cmdopts[] = { // clang-format off @@ -53,8 +56,8 @@ static int get_module_dirname(char *dirname_buf, size_t dirname_size, n = snprintf(dirname_buf, dirname_size, "%s/%s", module_directory, u.release); if (n >= (int)dirname_size) { - ERR("bad directory %s/%s: path too long\n", - module_directory, u.release); + SET_ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); return EXIT_FAILURE; } @@ -70,7 +73,7 @@ static int _do_lsmod(const char *dirname, int verbose) ctx = kmod_new(dirname, &null_config); if (!ctx) { - ERR("kmod_new() failed!\n"); + SET_ERR("kmod_new() failed!\n"); r = EXIT_FAILURE; goto finish; } @@ -79,7 +82,7 @@ static int _do_lsmod(const char *dirname, int verbose) err = kmod_module_new_from_loaded(ctx, &list); if (err < 0) { - ERR("could not get list of modules: %s\n", strerror(-err)); + SET_ERR("could not get list of modules: %s\n", strerror(-err)); r = EXIT_FAILURE; goto finish; } @@ -120,6 +123,8 @@ static int do_lsmod(int argc, char *argv[]) { char dirname_buf[PATH_MAX]; int verbose = LOG_ERR; + char *module_dir_error = NULL; + char *module_alt_dir_error = NULL; int use_syslog = 0; int c, r = 0; @@ -158,7 +163,12 @@ static int do_lsmod(int argc, char *argv[]) MODULE_DIRECTORY); if (!r) r = _do_lsmod(dirname_buf, verbose); - if (!r) + + if (r) + /* Store the error and print it *if* + * MODULE_ALTERNATIVE_DIRECTORY fails too */ + module_dir_error = pop_log_str(&error_log); + else /* MODULE_DIRECTORY was succesful */ goto done; @@ -168,8 +178,19 @@ static int do_lsmod(int argc, char *argv[]) MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_lsmod(dirname_buf, verbose); + + if (r) + /* Store the error and print it after MODULE_DIRECTORY */ + module_alt_dir_error = pop_log_str(&error_log); + else { + /* MODULE_ALTERNATIVE_DIRECTORY was succesful, no need to print + * module_dir_error */ + free(module_dir_error); + module_dir_error = NULL; + } #endif + PRINT_LOG_PTR(LOG_ERR, module_dir_error, module_alt_dir_error); done: log_close(); From 7ef5c7b08f65211a326112b646490ed1aa3b7ea3 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:17:01 -0500 Subject: [PATCH 27/32] tools/rmmod: move main logic into helpers Move code in do_rmmod into two helpers: one to get the dirname ($root/MODULE_DIRECTORY/$kernel) and another to do the main logic. The first helper, get_module_dirname(), is also always called to figure the dirname path and to avoid providing NULL to the kmod_new() API. This is because kmod_new() always defaults to MODULE_DIRECTORY when the dirname path is empty, and won't work when MODULE_ALTERNATIVE_DIRECTORY will be used. This is in preparation to perform the same two steps again for the new MODULE_ALTERNATIVE_DIRECTORY option. Signed-off-by: Emanuele Giuseppe Esposito --- tools/rmmod.c | 117 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/tools/rmmod.c b/tools/rmmod.c index 0e00edec..2d10fa6f 100644 --- a/tools/rmmod.c +++ b/tools/rmmod.c @@ -13,7 +13,9 @@ #include #include #include +#include +#include #include #include @@ -89,53 +91,38 @@ static int check_module_inuse(struct kmod_module *mod) return ret; } -static int do_rmmod(int argc, char *argv[]) +static int get_module_dirname(char *dirname_buf, size_t dirname_size, + const char *module_directory) { - struct kmod_ctx *ctx; - const char *null_config = NULL; - int verbose = LOG_ERR; - int use_syslog = 0; - int flags = 0; - int i, c, r = 0; - - while ((c = getopt_long(argc, argv, cmdopts_s, cmdopts, NULL)) != -1) { - switch (c) { - case 'f': - flags |= KMOD_REMOVE_FORCE; - break; - case 's': - use_syslog = 1; - break; - case 'v': - verbose++; - break; - case 'h': - help(); - return EXIT_SUCCESS; - case 'V': - kmod_version(); - return EXIT_SUCCESS; - case '?': - return EXIT_FAILURE; - default: - ERR("unexpected getopt_long() value '%c'.\n", c); - return EXIT_FAILURE; - } + struct utsname u; + int n; + + if (uname(&u) < 0) + return EXIT_FAILURE; + + n = snprintf(dirname_buf, dirname_size, + "%s/%s", module_directory, u.release); + if (n >= (int)dirname_size) { + ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); + return EXIT_FAILURE; } - log_open(use_syslog); + return EXIT_SUCCESS; +} - if (optind >= argc) { - ERR("missing module name.\n"); - r = EXIT_FAILURE; - goto done; - } +static int _do_rmmod(const char *dirname, int argc, char *argv[], int flags, + int verbose) +{ + struct kmod_ctx *ctx = NULL; + const char *null_config = NULL; + int r, i; - ctx = kmod_new(NULL, &null_config); + ctx = kmod_new(dirname, &null_config); if (!ctx) { ERR("kmod_new() failed!\n"); r = EXIT_FAILURE; - goto done; + goto finish; } log_setup_kmod_log(ctx, verbose); @@ -172,12 +159,62 @@ static int do_rmmod(int argc, char *argv[]) kmod_module_unref(mod); } +finish: kmod_unref(ctx); + return r; +} + +static int do_rmmod(int argc, char *argv[]) +{ + char dirname_buf[PATH_MAX]; + int verbose = LOG_ERR; + int use_syslog = 0; + int flags = 0; + int c, r = 0; + + while ((c = getopt_long(argc, argv, cmdopts_s, cmdopts, NULL)) != -1) { + switch (c) { + case 'f': + flags |= KMOD_REMOVE_FORCE; + break; + case 's': + use_syslog = 1; + break; + case 'v': + verbose++; + break; + case 'h': + help(); + return EXIT_SUCCESS; + case 'V': + kmod_version(); + return EXIT_SUCCESS; + case '?': + return EXIT_FAILURE; + default: + ERR("unexpected getopt_long() value '%c'.\n", c); + return EXIT_FAILURE; + } + } + + log_open(use_syslog); + + if (optind >= argc) { + ERR("missing module name.\n"); + r = EXIT_FAILURE; + goto done; + } + + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_DIRECTORY); + if (r) + goto done; + r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); done: log_close(); - return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return r; } const struct kmod_cmd kmod_cmd_compat_rmmod = { From 3cb11b691cd80a253aad402687a4c933fba24fe6 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 27 Nov 2024 11:17:48 -0500 Subject: [PATCH 28/32] tools/rmmod: add logic for MODULE_ALTERNATIVE_DIRECTORY If nothing is found in MODULE_DIRECTORY, perform the same exact steps but with MODULE_ALTERNATIVE_DIRECTORY. Signed-off-by: Emanuele Giuseppe Esposito --- tools/rmmod.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/rmmod.c b/tools/rmmod.c index 2d10fa6f..f7fa5015 100644 --- a/tools/rmmod.c +++ b/tools/rmmod.c @@ -205,11 +205,20 @@ static int do_rmmod(int argc, char *argv[]) goto done; } + /* Try first with MODULE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_DIRECTORY); - if (r) + if (!r) + r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); + if (!r) + /* MODULE_DIRECTORY was succesful */ goto done; - r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); + + /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ + r = get_module_dirname(dirname_buf, sizeof(dirname_buf), + MODULE_ALTERNATIVE_DIRECTORY); + if (!r) + r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); done: log_close(); From dd781c14ea2508c7e5f3e4c4d5d627ea77ba3b32 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 08:11:53 -0500 Subject: [PATCH 29/32] tools/rmmod: perform alternative directory lookup only if enabled -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- tools/rmmod.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/rmmod.c b/tools/rmmod.c index f7fa5015..49c77c2f 100644 --- a/tools/rmmod.c +++ b/tools/rmmod.c @@ -214,11 +214,13 @@ static int do_rmmod(int argc, char *argv[]) /* MODULE_DIRECTORY was succesful */ goto done; + #if ENABLE_ALTERNATIVE_DIR /* If not found, look at MODULE_ALTERNATIVE_DIRECTORY */ r = get_module_dirname(dirname_buf, sizeof(dirname_buf), MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); + #endif done: log_close(); From cdb9e3e0f691b4106604c0fc758c7dce90002c33 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 08:28:22 -0500 Subject: [PATCH 30/32] tools/rmmod: avoid redundant log messages -- can be squashed Using the macros developed in log.h, catch the error and print it only if both MODULE_DIRECTORY and MODULE_ALTERNATIVE_DIRECTORY call fail. Signed-off-by: Emanuele Giuseppe Esposito --- tools/rmmod.c | 55 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/tools/rmmod.c b/tools/rmmod.c index 49c77c2f..9102d021 100644 --- a/tools/rmmod.c +++ b/tools/rmmod.c @@ -22,6 +22,9 @@ #include "kmod.h" +LOG_PTR_INIT(error_log) +#define SET_ERR(...) SET_LOG_PTR(error_log, __VA_ARGS__) + static const char cmdopts_s[] = "fsvVh"; static const struct option cmdopts[] = { // clang-format off @@ -56,25 +59,33 @@ static int check_module_inuse(struct kmod_module *mod) state = kmod_module_get_initstate(mod); if (state == KMOD_MODULE_BUILTIN) { - ERR("Module %s is builtin.\n", kmod_module_get_name(mod)); + SET_ERR("Module %s is builtin.\n", kmod_module_get_name(mod)); return -ENOENT; } else if (state < 0) { - ERR("Module %s is not currently loaded\n", kmod_module_get_name(mod)); + SET_ERR("Module %s is not currently loaded\n", + kmod_module_get_name(mod)); return -ENOENT; } holders = kmod_module_get_holders(mod); if (holders != NULL) { struct kmod_list *itr; + char *mod_list = NULL, *old_mod; - ERR("Module %s is in use by:", kmod_module_get_name(mod)); + if (asprintf(&mod_list, "Module %s is in use by:", kmod_module_get_name(mod)) < 0) + return -ENOMEM; kmod_list_foreach(itr, holders) { struct kmod_module *hm = kmod_module_get_module(itr); - ERR(" %s", kmod_module_get_name(hm)); + old_mod = mod_list; + ret = asprintf(&mod_list, "%s %s", old_mod, kmod_module_get_name(hm)); + free(old_mod); kmod_module_unref(hm); + if (ret < 0) + return -ENOMEM; } - ERR("\n"); + SET_ERR("%s\n", mod_list); + free(mod_list); kmod_module_unref_list(holders); return -EBUSY; @@ -82,10 +93,10 @@ static int check_module_inuse(struct kmod_module *mod) ret = kmod_module_get_refcnt(mod); if (ret > 0) { - ERR("Module %s is in use\n", kmod_module_get_name(mod)); + SET_ERR("Module %s is in use\n", kmod_module_get_name(mod)); return -EBUSY; } else if (ret == -ENOENT) { - ERR("Module unloading is not supported\n"); + SET_ERR("Module unloading is not supported\n"); } return ret; @@ -103,8 +114,8 @@ static int get_module_dirname(char *dirname_buf, size_t dirname_size, n = snprintf(dirname_buf, dirname_size, "%s/%s", module_directory, u.release); if (n >= (int)dirname_size) { - ERR("bad directory %s/%s: path too long\n", - module_directory, u.release); + SET_ERR("bad directory %s/%s: path too long\n", + module_directory, u.release); return EXIT_FAILURE; } @@ -120,7 +131,7 @@ static int _do_rmmod(const char *dirname, int argc, char *argv[], int flags, ctx = kmod_new(dirname, &null_config); if (!ctx) { - ERR("kmod_new() failed!\n"); + SET_ERR("kmod_new() failed!\n"); r = EXIT_FAILURE; goto finish; } @@ -139,7 +150,7 @@ static int _do_rmmod(const char *dirname, int argc, char *argv[], int flags, err = kmod_module_new_from_name(ctx, arg, &mod); if (err < 0) { - ERR("could not use module %s: %s\n", arg, strerror(-err)); + SET_ERR("could not use module %s: %s\n", arg, strerror(-err)); r = EXIT_FAILURE; break; } @@ -152,7 +163,7 @@ static int _do_rmmod(const char *dirname, int argc, char *argv[], int flags, err = kmod_module_remove_module(mod, flags); if (err < 0) { - ERR("could not remove module %s: %s\n", arg, strerror(-err)); + SET_ERR("could not remove module %s: %s\n", arg, strerror(-err)); r = EXIT_FAILURE; } @@ -168,6 +179,8 @@ static int do_rmmod(int argc, char *argv[]) { char dirname_buf[PATH_MAX]; int verbose = LOG_ERR; + char *module_dir_error = NULL; + char *module_alt_dir_error = NULL; int use_syslog = 0; int flags = 0; int c, r = 0; @@ -210,7 +223,12 @@ static int do_rmmod(int argc, char *argv[]) MODULE_DIRECTORY); if (!r) r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); - if (!r) + + if (r) + /* Store the error and print it *if* + * MODULE_ALTERNATIVE_DIRECTORY fails too */ + module_dir_error = pop_log_str(&error_log); + else /* MODULE_DIRECTORY was succesful */ goto done; @@ -220,8 +238,19 @@ static int do_rmmod(int argc, char *argv[]) MODULE_ALTERNATIVE_DIRECTORY); if (!r) r = _do_rmmod(dirname_buf, argc, argv, flags, verbose); + + if (r) + /* Store the error and print it after MODULE_DIRECTORY */ + module_alt_dir_error = pop_log_str(&error_log); + else { + /* MODULE_ALTERNATIVE_DIRECTORY was succesful, no need to print + * module_dir_error */ + free(module_dir_error); + module_dir_error = NULL; + } #endif + PRINT_LOG_PTR(LOG_ERR, module_dir_error, module_alt_dir_error); done: log_close(); From d8701291347e06f6e73ca50213f604fbea8e0ea6 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 27 Jan 2025 09:22:41 -0500 Subject: [PATCH 31/32] man: add MODULE_ALTERNATIVE_DIRECTORY documentation Esplicitly define MODULE_ALTERNATIVE_DIRECTORY in the docs as fallback directory if MODULE_DIRECTORY is missing or the module is not present there. Signed-off-by: Emanuele Giuseppe Esposito --- man/insmod.8.scd | 6 ++++++ man/lsmod.8.scd | 3 +++ man/modinfo.8.scd | 15 ++++++++++++--- man/modprobe.8.scd | 23 +++++++++++++++++++++++ man/rmmod.8.scd | 6 ++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/man/insmod.8.scd b/man/insmod.8.scd index a5c42646..30981acc 100644 --- a/man/insmod.8.scd +++ b/man/insmod.8.scd @@ -18,6 +18,12 @@ Only the most general of error messages are reported: as the work of trying to link the module is now done inside the kernel, the *dmesg*(1) usually gives more information about errors. +*insmod* will look by default at modules stored in @MODULE_DIRECTORY@, but if +the folder is missing or the module is not found, it will automatically look at +the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. +This program will fail only if the provided module is not found in both +directories. + # OPTIONS *-f*, *--force* diff --git a/man/lsmod.8.scd b/man/lsmod.8.scd index 339526df..519f51b0 100644 --- a/man/lsmod.8.scd +++ b/man/lsmod.8.scd @@ -13,6 +13,9 @@ lsmod - Show the status of modules in the Linux Kernel *lsmod* is a trivial program which nicely formats the contents of the _/proc/modules_, showing what kernel modules are currently loaded. +*lsmod* will look by default at modules stored in @MODULE_DIRECTORY@, but if +the folder is missing , it will automatically look at the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. + # OPTIONS *-s*, *--syslog* diff --git a/man/modinfo.8.scd b/man/modinfo.8.scd index c64e9c82..beb6781e 100644 --- a/man/modinfo.8.scd +++ b/man/modinfo.8.scd @@ -15,9 +15,18 @@ modinfo - Show information about a Linux Kernel module # DESCRIPTION *modinfo* extracts information from the Linux Kernel modules given on the -command line. If the module name is not a filename, then the @MODULE_DIRECTORY@/ -_version_ directory is searched, as is also done by *modprobe*(8) when loading -kernel modules. +command line. + +*modinfo* will search by default for modules stored in @MODULE_DIRECTORY@, but +if the folder is missing or the module is not found, it will automatically look +at the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. +This program will fail only if the provided module is not found in both +directories. + +If the module name is not a filename, then the @MODULE_DIRECTORY@/ +_version_ directory is searched first, and then +@MODULE_ALTERNATIVE_DIRECTORY@/_version_, as is also done by *modprobe*(8) when +loading kernel modules. *modinfo* by default lists each attribute of the module in form _fieldname_ : _value_, for easy reading. The filename is listed the same way (although it's diff --git a/man/modprobe.8.scd b/man/modprobe.8.scd index 075704d8..6e188dfe 100644 --- a/man/modprobe.8.scd +++ b/man/modprobe.8.scd @@ -44,6 +44,29 @@ is relative, it must explicitly start with "./". Note that this may fail when using a path to a module with dependencies not matching the installed *depmod* database. +*modprobe* will search by default for modules stored in @MODULE_DIRECTORY@, but +if the folder is missing or the module is not found, it will automatically look +at the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. +This program will fail only if the provided module is not found in both +directories. + +The rationale for @MODULE_ALTERNATIVE_DIRECTORY@ is that this folder could be +used to reference pre-build or distro-provided default modules, and leave +@MODULE_DIRECTORY@ to point custom locally generated modules. In this way, the +first lookup always happens in @MODULE_DIRECTORY@ and will always reference the +local modules, but if for some reason some module is missing, +@MODULE_ALTERNATIVE_DIRECTORY@ could be used as fallback as source of default +standard modules. + +Another specific use case for this is with UKIs (Unified Kernel Image). +In this scenario, there is the possibility of not keeping two copies of the +kernel modules (one for initramfs and not for rootfs), but instead copy the ones +in initramfs to tmpfs, e.g. in /run/modules. Note that modules are not directly +copied in rootfs because it might also be read-only mounted. +This copy is feasible because an UKI ships kernel and initramfs together, so +there is no need to locally build anything, avoiding kernel-initramfs version +mismatches. + # OPTIONS *-a*, *--all* diff --git a/man/rmmod.8.scd b/man/rmmod.8.scd index 2f6bd56c..c3527d5a 100644 --- a/man/rmmod.8.scd +++ b/man/rmmod.8.scd @@ -15,6 +15,12 @@ kernel (when module unloading support is provided). Most users will want to use *modprobe*(8) with the *-r* option instead since it removes unused dependent modules as well. +*rmmod* will look by default at modules stored in @MODULE_DIRECTORY@, but if +the folder is missing or the module is not found, it will automatically look at +the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. +This program will fail only if the provided module is not found in both +directories. + When a list of modules is provided, the program will process them one at a time. If a module is not found, *rmmod* will immediately exit with an error code. Should the module removal fail, the program will log an error AND continue with From c0bbebfbddd1d07a8ccfaf5c5f67f0f5ddcc4a72 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 3 Feb 2025 08:38:15 -0500 Subject: [PATCH 32/32] man: mention enable-alternative-dir flag at compile time -- can be squashed Signed-off-by: Emanuele Giuseppe Esposito --- man/insmod.8.scd | 9 +++++---- man/modinfo.8.scd | 11 ++++++----- man/modprobe.8.scd | 9 +++++---- man/rmmod.8.scd | 9 +++++---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/man/insmod.8.scd b/man/insmod.8.scd index 30981acc..475f1910 100644 --- a/man/insmod.8.scd +++ b/man/insmod.8.scd @@ -19,10 +19,11 @@ link the module is now done inside the kernel, the *dmesg*(1) usually gives more information about errors. *insmod* will look by default at modules stored in @MODULE_DIRECTORY@, but if -the folder is missing or the module is not found, it will automatically look at -the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. -This program will fail only if the provided module is not found in both -directories. +the folder is missing or the module is not found and kmod is compiled with +@enable-alternative-dir=true@, it will automatically look at the fallback +directory @MODULE_ALTERNATIVE_DIRECTORY@. +In that case, this program will only fail if the provided module is not found in +both directories. # OPTIONS diff --git a/man/modinfo.8.scd b/man/modinfo.8.scd index beb6781e..bff5a7aa 100644 --- a/man/modinfo.8.scd +++ b/man/modinfo.8.scd @@ -18,13 +18,14 @@ modinfo - Show information about a Linux Kernel module command line. *modinfo* will search by default for modules stored in @MODULE_DIRECTORY@, but -if the folder is missing or the module is not found, it will automatically look -at the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. -This program will fail only if the provided module is not found in both -directories. +if the folder is missing or the module is not found and kmod is compiled with +@enable-alternative-dir=true@, it will automatically look at the fallback +directory @MODULE_ALTERNATIVE_DIRECTORY@. +In that case, this program will only fail if the provided module is not found in +both directories. If the module name is not a filename, then the @MODULE_DIRECTORY@/ -_version_ directory is searched first, and then +_version_ directory is searched first, and then if enabled @MODULE_ALTERNATIVE_DIRECTORY@/_version_, as is also done by *modprobe*(8) when loading kernel modules. diff --git a/man/modprobe.8.scd b/man/modprobe.8.scd index 6e188dfe..2a18e496 100644 --- a/man/modprobe.8.scd +++ b/man/modprobe.8.scd @@ -45,10 +45,11 @@ using a path to a module with dependencies not matching the installed *depmod* database. *modprobe* will search by default for modules stored in @MODULE_DIRECTORY@, but -if the folder is missing or the module is not found, it will automatically look -at the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. -This program will fail only if the provided module is not found in both -directories. +if the folder is missing or the module is not found and kmod is compiled with +@enable-alternative-dir=true@, it will automatically look at the fallback +directory @MODULE_ALTERNATIVE_DIRECTORY@. +In that case, this program will only fail if the provided module is not found in +both directories. The rationale for @MODULE_ALTERNATIVE_DIRECTORY@ is that this folder could be used to reference pre-build or distro-provided default modules, and leave diff --git a/man/rmmod.8.scd b/man/rmmod.8.scd index c3527d5a..5a4b3b24 100644 --- a/man/rmmod.8.scd +++ b/man/rmmod.8.scd @@ -16,10 +16,11 @@ kernel (when module unloading support is provided). Most users will want to use modules as well. *rmmod* will look by default at modules stored in @MODULE_DIRECTORY@, but if -the folder is missing or the module is not found, it will automatically look at -the fallback directory @MODULE_ALTERNATIVE_DIRECTORY@. -This program will fail only if the provided module is not found in both -directories. +the folder is missing or the module is not found and kmod is compiled with +@enable-alternative-dir=true@, it will automatically look at the fallback +directory @MODULE_ALTERNATIVE_DIRECTORY@. +In that case, this program will only fail if the provided module is not found in +both directories. When a list of modules is provided, the program will process them one at a time. If a module is not found, *rmmod* will immediately exit with an error code.