In line with m-i-t's behavior, we should check to see if each module is:

- loaded
- has any holders
- has a 0 refcnt

Detecting any of these lets us provide a more useful message than the
kernel's EPERM response to delete_module(2).

Additionally, alter the main loop behavior to avoid exiting early on the
first error.
---
 tools/kmod-rmmod.c |   35 +++++++++++++++++++++++++++++++----
 1 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/tools/kmod-rmmod.c b/tools/kmod-rmmod.c
index 658ff6b..029621f 100644
--- a/tools/kmod-rmmod.c
+++ b/tools/kmod-rmmod.c
@@ -107,7 +107,7 @@ static int do_rmmod(int argc, char *argv[])
        int flags = KMOD_REMOVE_NOWAIT;
        int use_syslog = 0;
        int verbose = 0;
-       int i, err = 0;
+       int i, err, r = 0;
 
        for (;;) {
                int c, idx = 0;
@@ -162,6 +162,8 @@ static int do_rmmod(int argc, char *argv[])
 
        for (i = optind; i < argc; i++) {
                struct kmod_module *mod;
+               struct kmod_list *holders;
+               int use_count;
                const char *arg = argv[i];
                struct stat st;
                if (stat(arg, &st) == 0)
@@ -175,15 +177,40 @@ static int do_rmmod(int argc, char *argv[])
                        break;
                }
 
+               if (kmod_module_get_initstate(mod) == -ENOENT) {
+                       fprintf(stderr, "Error: Module %s is not currently 
loaded\n",
+                                       kmod_module_get_name(mod));
+                       goto next;
+               }
+
+               holders = kmod_module_get_holders(mod);
+               if (holders != NULL) {
+                       struct kmod_module *hm = 
kmod_module_get_module(holders);
+                       fprintf(stderr, "Error: Module %s is in use by %s\n",
+                                       kmod_module_get_name(mod), 
kmod_module_get_name(hm));
+                       kmod_module_unref_list(holders);
+                       kmod_module_unref(hm);
+                       r++;
+                       goto next;
+               }
+
+               use_count = kmod_module_get_refcnt(mod);
+               if (use_count != 0) {
+                       fprintf(stderr, "Error: Module %s is in use\n",
+                                       kmod_module_get_name(mod));
+                       r++;
+                       goto next;
+               }
+
                err = kmod_module_remove_module(mod, flags);
                if (err < 0) {
                        fprintf(stderr,
                                "Error: could not remove module %s: %s\n",
                                arg, strerror(-err));
+                       r++;
                }
+next:
                kmod_module_unref(mod);
-               if (err < 0)
-                       break;
        }
 
        kmod_unref(ctx);
@@ -191,7 +218,7 @@ static int do_rmmod(int argc, char *argv[])
        if (use_syslog)
                closelog();
 
-       return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+       return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
 #ifndef KMOD_BUNDLE_TOOL
-- 
1.7.8.3

--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to