modprobe-small: fix and simplify rmmod
"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@googlemail.com>
This commit is contained in:
parent
782ee2aa0e
commit
68c048fb23
@ -549,9 +549,23 @@ static int already_loaded(const char *name)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define already_loaded(name) is_rmmod
|
#define already_loaded(name) 0
|
||||||
#endif
|
#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)
|
* Given modules definition and module name (or alias, or symbol)
|
||||||
* load/remove the module respecting dependencies.
|
* 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 **infovec;
|
||||||
module_info *info;
|
module_info *info;
|
||||||
int infoidx;
|
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);
|
dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
|
||||||
|
|
||||||
replace(name, '-', '_');
|
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
|
* modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
|
||||||
* won't unload modules (there are more than one)
|
* won't unload modules (there are more than one)
|
||||||
* which have this alias.
|
* 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);
|
dbg1_error_msg("nothing to do for '%s'", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
options = NULL;
|
options = NULL;
|
||||||
if (!is_rmmod) {
|
if (!is_remove) {
|
||||||
char *opt_filename = xasprintf("/etc/modules/%s", name);
|
char *opt_filename = xasprintf("/etc/modules/%s", name);
|
||||||
options = xmalloc_open_read_close(opt_filename, NULL);
|
options = xmalloc_open_read_close(opt_filename, NULL);
|
||||||
if (options)
|
if (options)
|
||||||
@ -621,7 +645,7 @@ static void process_module(char *name, const char *cmdline_options)
|
|||||||
0 /* depth */
|
0 /* depth */
|
||||||
);
|
);
|
||||||
dbg1_error_msg("dirscan complete");
|
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 */
|
if (module_found_idx >= 0) { /* module was found */
|
||||||
infovec = xzalloc(2 * sizeof(infovec[0]));
|
infovec = xzalloc(2 * sizeof(infovec[0]));
|
||||||
infovec[0] = &modinfo[module_found_idx];
|
infovec[0] = &modinfo[module_found_idx];
|
||||||
@ -634,7 +658,7 @@ static void process_module(char *name, const char *cmdline_options)
|
|||||||
|
|
||||||
if (!infovec) {
|
if (!infovec) {
|
||||||
/* both dirscan and find_alias found nothing */
|
/* 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);
|
bb_error_msg("module '%s' not found", name);
|
||||||
//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
|
//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -648,29 +672,15 @@ static void process_module(char *name, const char *cmdline_options)
|
|||||||
* a *list* of modinfo pointers from find_alias().
|
* a *list* of modinfo pointers from find_alias().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* rmmod or modprobe -r? unload module(s) */
|
/* modprobe -r? unload module(s) */
|
||||||
if (is_rmmod) {
|
if (is_remove) {
|
||||||
infoidx = 0;
|
infoidx = 0;
|
||||||
while ((info = infovec[infoidx++]) != NULL) {
|
while ((info = infovec[infoidx++]) != NULL) {
|
||||||
int r;
|
int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
|
||||||
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);
|
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
if (!(option_mask32 & OPT_q))
|
goto ret; /* error */
|
||||||
bb_perror_msg("remove '%s'", modname);
|
|
||||||
goto ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applet_name[0] == 'r') {
|
|
||||||
/* rmmod: do not remove dependencies, exit */
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* modprobe -r: we do not stop here -
|
/* modprobe -r: we do not stop here -
|
||||||
* continue to unload modules on which the module depends:
|
* continue to unload modules on which the module depends:
|
||||||
* "-r --remove: option causes modprobe to remove a module.
|
* "-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);
|
free(deps);
|
||||||
|
|
||||||
if (is_rmmod)
|
if (is_remove)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* We are modprobe: load it */
|
/* 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 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. */
|
* insmod/modprobe takes one module name, the rest are parameters. */
|
||||||
options = NULL;
|
options = NULL;
|
||||||
if ('r' != applet0) {
|
if (!(option_mask32 & OPT_r)) {
|
||||||
char **arg = argv;
|
char **arg = argv;
|
||||||
while (*++arg) {
|
while (*++arg) {
|
||||||
/* Enclose options in quotes */
|
/* Enclose options in quotes */
|
||||||
@ -908,7 +918,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ('r' != applet0)
|
if (!(option_mask32 & OPT_r))
|
||||||
argv[1] = NULL;
|
argv[1] = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -932,10 +942,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try to load modprobe.dep.bb */
|
/* Try to load modprobe.dep.bb */
|
||||||
load_dep_bb();
|
if ('r' != applet0) /* not rmmod */
|
||||||
|
load_dep_bb();
|
||||||
|
|
||||||
/* Load/remove modules.
|
/* 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 {
|
do {
|
||||||
process_module(*argv, options);
|
process_module(*argv, options);
|
||||||
} while (*++argv);
|
} while (*++argv);
|
||||||
|
Loading…
Reference in New Issue
Block a user