mirror of
https://github.com/AuxXxilium/kmod.git
synced 2024-11-24 07:20:52 +07:00
modprobe: rework module removal without tree traversing
Just like the module insertion, module removal is remade. The dependencies line that comes from modules.dep already contains all the dependencies necessary to remove that module. Therefore modprobe doesn't have to do the recursion between the modules in order to remove it. All we have to do is to remove in order: For the module being removed: ---------------------------- 1. softdeps (in reverse order) 2. deps (in reverse order) 3. module 4. postdeps (in reverse order) For any of the dependencies: ---------------------------- 1. softdeps (in reverse order) 2. module 3. softdeps (in reverse order)
This commit is contained in:
parent
f564394f99
commit
a872bba22d
@ -305,132 +305,56 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rmmod_do_dependencies(struct kmod_module *parent);
|
||||
static int rmmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps);
|
||||
|
||||
static int rmmod_do_deps_list(struct kmod_module *parent,
|
||||
struct kmod_list *deps,
|
||||
unsigned stop_on_errors)
|
||||
static int rmmod_do_remove_module(struct kmod_module *mod)
|
||||
{
|
||||
struct kmod_list *d;
|
||||
int err = 0;
|
||||
const char *modname = kmod_module_get_name(mod);
|
||||
int flags = 0, err;
|
||||
|
||||
kmod_list_foreach_reverse(d, deps) {
|
||||
struct kmod_module *dm = kmod_module_get_module(d);
|
||||
struct kmod_list *pre = NULL, *post = NULL;
|
||||
const char *cmd, *dmname = kmod_module_get_name(dm);
|
||||
int r;
|
||||
SHOW("rmmod %s\n", kmod_module_get_name(mod));
|
||||
|
||||
r = rmmod_do_dependencies(dm);
|
||||
if (r < 0) {
|
||||
WRN("could not remove dependencies of '%s': %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
}
|
||||
if (dry_run)
|
||||
return 0;
|
||||
|
||||
r = kmod_module_get_softdeps(dm, &pre, &post);
|
||||
if (r < 0) {
|
||||
WRN("could not get softdeps of '%s': %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_done;
|
||||
}
|
||||
if (force)
|
||||
flags |= KMOD_REMOVE_FORCE;
|
||||
|
||||
r = rmmod_do_soft_dependencies(dm, post);
|
||||
if (r < 0) {
|
||||
WRN("could not remove post soft softdeps of '%s': %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
}
|
||||
|
||||
if (!ignore_loaded) {
|
||||
int state = kmod_module_get_initstate(dm);
|
||||
if (state != KMOD_MODULE_LIVE &&
|
||||
state != KMOD_MODULE_COMING)
|
||||
goto dep_done;
|
||||
}
|
||||
|
||||
cmd = kmod_module_get_remove_commands(dm);
|
||||
if (cmd) {
|
||||
r = command_do(dm, "remove", cmd, NULL);
|
||||
if (r < 0) {
|
||||
WRN("failed to execute remove command of '%s': "
|
||||
"%s\n", dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
} else
|
||||
goto dep_done;
|
||||
}
|
||||
|
||||
r = kmod_module_get_refcnt(dm);
|
||||
if (r < 0) {
|
||||
WRN("could not get module '%s' refcnt: %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
} else if (r > 0 && !ignore_loaded) {
|
||||
LOG("Module %s is in use.\n", dmname);
|
||||
r = -EBUSY;
|
||||
goto dep_error;
|
||||
}
|
||||
|
||||
SHOW("rmmod %s\n", dmname);
|
||||
|
||||
if (!dry_run) {
|
||||
r = kmod_module_remove_module(dm, 0);
|
||||
if (r < 0) {
|
||||
WRN("could not remove '%s': %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
}
|
||||
}
|
||||
|
||||
dep_done:
|
||||
r = rmmod_do_soft_dependencies(dm, pre);
|
||||
if (r < 0) {
|
||||
WRN("could not remove pre softdeps of '%s': %s\n",
|
||||
dmname, strerror(-r));
|
||||
goto dep_error;
|
||||
}
|
||||
kmod_module_unref_list(pre);
|
||||
kmod_module_unref_list(post);
|
||||
kmod_module_unref(dm);
|
||||
continue;
|
||||
|
||||
dep_error:
|
||||
err = r;
|
||||
kmod_module_unref_list(pre);
|
||||
kmod_module_unref_list(post);
|
||||
kmod_module_unref(dm);
|
||||
if (stop_on_errors)
|
||||
break;
|
||||
err = kmod_module_remove_module(mod, flags);
|
||||
if (err == -EEXIST) {
|
||||
if (!first_time)
|
||||
err = 0;
|
||||
else
|
||||
continue;
|
||||
LOG("Module %s is not in kernel.\n", modname);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rmmod_do_soft_dependencies(struct kmod_module *mod,
|
||||
struct kmod_list *deps)
|
||||
static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies);
|
||||
|
||||
static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
|
||||
{
|
||||
return rmmod_do_deps_list(mod, deps, 0);
|
||||
struct kmod_list *l;
|
||||
|
||||
kmod_list_foreach_reverse(l, list) {
|
||||
struct kmod_module *m = kmod_module_get_module(l);
|
||||
int r = rmmod_do_module(m, false);
|
||||
kmod_module_unref(m);
|
||||
|
||||
if (r < 0 && stop_on_errors)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmmod_do_dependencies(struct kmod_module *parent)
|
||||
{
|
||||
struct kmod_list *deps = kmod_module_get_holders(parent);
|
||||
int err = rmmod_do_deps_list(parent, deps, 1);
|
||||
kmod_module_unref_list(deps);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rmmod_do(struct kmod_module *mod)
|
||||
static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies)
|
||||
{
|
||||
const char *modname = kmod_module_get_name(mod);
|
||||
struct kmod_list *pre = NULL, *post = NULL, *deps;
|
||||
struct kmod_list *pre = NULL, *post = NULL;
|
||||
const char *cmd = NULL;
|
||||
int err;
|
||||
|
||||
if (!ignore_commands) {
|
||||
const char *cmd;
|
||||
|
||||
err = kmod_module_get_softdeps(mod, &pre, &post);
|
||||
if (err < 0) {
|
||||
WRN("could not get softdeps of '%s': %s\n",
|
||||
@ -438,21 +362,10 @@ static int rmmod_do(struct kmod_module *mod)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = rmmod_do_soft_dependencies(mod, post);
|
||||
if (err < 0) {
|
||||
WRN("could not remove post softdeps of '%s': %s\n",
|
||||
modname, strerror(-err));
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmd = kmod_module_get_remove_commands(mod);
|
||||
if (cmd != NULL) {
|
||||
err = command_do(mod, "remove", cmd, NULL);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore_loaded) {
|
||||
if (cmd == NULL && !ignore_loaded) {
|
||||
int state = kmod_module_get_initstate(mod);
|
||||
|
||||
if (state < 0) {
|
||||
@ -470,11 +383,14 @@ static int rmmod_do(struct kmod_module *mod)
|
||||
}
|
||||
}
|
||||
|
||||
/* not in original modprobe -r, but helpful */
|
||||
if (remove_dependencies) {
|
||||
err = rmmod_do_dependencies(mod);
|
||||
rmmod_do_deps_list(post, false);
|
||||
|
||||
if (do_dependencies && remove_dependencies) {
|
||||
struct kmod_list *deps = kmod_module_get_dependencies(mod);
|
||||
|
||||
err = rmmod_do_deps_list(deps, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!ignore_loaded) {
|
||||
@ -485,62 +401,24 @@ static int rmmod_do(struct kmod_module *mod)
|
||||
LOG("Module %s is in use.\n", modname);
|
||||
|
||||
err = -EBUSY;
|
||||
goto done_deps;
|
||||
}
|
||||
}
|
||||
|
||||
SHOW("rmmod %s\n", modname);
|
||||
|
||||
if (dry_run)
|
||||
err = 0;
|
||||
else {
|
||||
int flags = 0;
|
||||
|
||||
if (force)
|
||||
flags |= KMOD_REMOVE_FORCE;
|
||||
|
||||
err = kmod_module_remove_module(mod, flags);
|
||||
if (err == -EEXIST) {
|
||||
if (!first_time)
|
||||
err = 0;
|
||||
else
|
||||
LOG("Module %s is not in kernel.\n", modname);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!ignore_commands) {
|
||||
err = rmmod_do_soft_dependencies(mod, pre);
|
||||
if (err < 0) {
|
||||
WRN("could not remove pre softdeps of '%s': %s\n",
|
||||
modname, strerror(-err));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
done_deps:
|
||||
deps = kmod_module_get_dependencies(mod);
|
||||
if (deps != NULL) {
|
||||
struct kmod_list *itr;
|
||||
if (cmd == NULL)
|
||||
err = rmmod_do_remove_module(mod);
|
||||
else
|
||||
err = command_do(mod, "remove", cmd, NULL);
|
||||
|
||||
first_time = 0;
|
||||
ignore_commands = 0;
|
||||
quiet_inuse = 1;
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
kmod_list_foreach(itr, deps) {
|
||||
struct kmod_module *dep = kmod_module_get_module(itr);
|
||||
|
||||
if (kmod_module_get_refcnt(dep) == 0)
|
||||
rmmod_do(dep);
|
||||
|
||||
kmod_module_unref(dep);
|
||||
}
|
||||
kmod_module_unref_list(deps);
|
||||
}
|
||||
rmmod_do_deps_list(pre, false);
|
||||
|
||||
error:
|
||||
kmod_module_unref_list(pre);
|
||||
kmod_module_unref_list(post);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -554,7 +432,7 @@ static int rmmod_path(struct kmod_ctx *ctx, const char *path)
|
||||
LOG("Module %s not found.\n", path);
|
||||
return err;
|
||||
}
|
||||
err = rmmod_do(mod);
|
||||
err = rmmod_do_module(mod, true);
|
||||
kmod_module_unref(mod);
|
||||
return err;
|
||||
}
|
||||
@ -573,7 +451,7 @@ static int rmmod_alias(struct kmod_ctx *ctx, const char *alias)
|
||||
|
||||
kmod_list_foreach(l, list) {
|
||||
struct kmod_module *mod = kmod_module_get_module(l);
|
||||
err = rmmod_do(mod);
|
||||
err = rmmod_do_module(mod, true);
|
||||
kmod_module_unref(mod);
|
||||
if (err < 0)
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user