[git commit] modprobe-small: fix and simplify rmmod
Denys Vlasenko
vda.linux at googlemail.com
Sat Feb 7 19:44:46 UTC 2015
commit: http://git.busybox.net/busybox/commit/?id=68c048fb23bd8b0831bbd02ec66900b12390cf19
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master
"rmmod OUT_OF_TREE_MODULE" was not working, because module is not in depmod file.
In general, rmmod doesn't need scanning, it simply unloads every argv[i].
function old new delta
rmmod - 63 +63
modprobe_main 449 465 +16
process_module 705 667 -38
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 79/-38) Total: 41 bytes
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
modutils/modprobe-small.c | 75 +++++++++++++++++++++++++-------------------
1 files changed, 43 insertions(+), 32 deletions(-)
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index cafbdc0..6b0a440 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -549,9 +549,23 @@ static int already_loaded(const char *name)
return ret;
}
#else
-#define already_loaded(name) is_rmmod
+#define already_loaded(name) 0
#endif
+static int rmmod(const char *filename)
+{
+ int r;
+ char modname[MODULE_NAME_LEN];
+
+ filename2modname(filename, modname);
+ r = delete_module(modname, O_NONBLOCK | O_EXCL);
+ dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
+ if (r != 0 && !(option_mask32 & OPT_q)) {
+ bb_perror_msg("remove '%s'", modname);
+ }
+ return r;
+}
+
/*
* Given modules definition and module name (or alias, or symbol)
* load/remove the module respecting dependencies.
@@ -568,26 +582,36 @@ static void process_module(char *name, const char *cmdline_options)
module_info **infovec;
module_info *info;
int infoidx;
- int is_rmmod = (option_mask32 & OPT_r) != 0;
+ int is_remove = (option_mask32 & OPT_r) != 0;
dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
replace(name, '-', '_');
- dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod);
+ dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
+
+ if (applet_name[0] == 'r') {
+ /* rmmod.
+ * Does not remove dependencies, no need to scan, just remove.
+ * (compat note: this allows and strips .ko suffix)
+ */
+ rmmod(name);
+ return;
+ }
+
/*
- * We used to have "is_rmmod != already_loaded(name)" check here, but
+ * We used to have "is_remove != already_loaded(name)" check here, but
* modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
* won't unload modules (there are more than one)
* which have this alias.
*/
- if (!is_rmmod && already_loaded(name)) {
+ if (!is_remove && already_loaded(name)) {
dbg1_error_msg("nothing to do for '%s'", name);
return;
}
options = NULL;
- if (!is_rmmod) {
+ if (!is_remove) {
char *opt_filename = xasprintf("/etc/modules/%s", name);
options = xmalloc_open_read_close(opt_filename, NULL);
if (options)
@@ -621,7 +645,7 @@ static void process_module(char *name, const char *cmdline_options)
0 /* depth */
);
dbg1_error_msg("dirscan complete");
- /* Module was not found, or load failed, or is_rmmod */
+ /* Module was not found, or load failed, or is_remove */
if (module_found_idx >= 0) { /* module was found */
infovec = xzalloc(2 * sizeof(infovec[0]));
infovec[0] = &modinfo[module_found_idx];
@@ -634,7 +658,7 @@ static void process_module(char *name, const char *cmdline_options)
if (!infovec) {
/* both dirscan and find_alias found nothing */
- if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
+ if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
bb_error_msg("module '%s' not found", name);
//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
goto ret;
@@ -648,29 +672,15 @@ static void process_module(char *name, const char *cmdline_options)
* a *list* of modinfo pointers from find_alias().
*/
- /* rmmod or modprobe -r? unload module(s) */
- if (is_rmmod) {
+ /* modprobe -r? unload module(s) */
+ if (is_remove) {
infoidx = 0;
while ((info = infovec[infoidx++]) != NULL) {
- int r;
- char modname[MODULE_NAME_LEN];
-
- filename2modname(
- bb_get_last_path_component_nostrip(info->pathname), modname);
- r = delete_module(modname, O_NONBLOCK | O_EXCL);
- dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
+ int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
if (r != 0) {
- if (!(option_mask32 & OPT_q))
- bb_perror_msg("remove '%s'", modname);
- goto ret;
+ goto ret; /* error */
}
}
-
- if (applet_name[0] == 'r') {
- /* rmmod: do not remove dependencies, exit */
- goto ret;
- }
-
/* modprobe -r: we do not stop here -
* continue to unload modules on which the module depends:
* "-r --remove: option causes modprobe to remove a module.
@@ -691,7 +701,7 @@ static void process_module(char *name, const char *cmdline_options)
}
free(deps);
- if (is_rmmod)
+ if (is_remove)
continue;
/* We are modprobe: load it */
@@ -894,10 +904,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
}
#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
- /* If not rmmod, parse possible module options given on command line.
+ /* If not rmmod/-r, parse possible module options given on command line.
* insmod/modprobe takes one module name, the rest are parameters. */
options = NULL;
- if ('r' != applet0) {
+ if (!(option_mask32 & OPT_r)) {
char **arg = argv;
while (*++arg) {
/* Enclose options in quotes */
@@ -908,7 +918,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
}
}
#else
- if ('r' != applet0)
+ if (!(option_mask32 & OPT_r))
argv[1] = NULL;
#endif
@@ -932,10 +942,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
}
/* Try to load modprobe.dep.bb */
- load_dep_bb();
+ if ('r' != applet0) /* not rmmod */
+ load_dep_bb();
/* Load/remove modules.
- * Only rmmod loops here, modprobe has only argv[0] */
+ * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
do {
process_module(*argv, options);
} while (*++argv);
More information about the busybox-cvs
mailing list