[illumos-Developer] [PATCH] modload: Unload modules by name
Alexey Zaytsev
alexey.zaytsev at gmail.com
Thu May 26 14:57:31 PDT 2011
Signed-off-by: Alexey Zaytsev <alexey.zaytsev at gmail.com>
---
Hi.
I've seen all new nexenta people submit their first patches into
illumos pretty quick, so to solidify this tradition, here's one from me.
It lets you unload modules by name, as simple as
modunload vioif virtio
And yes, it takes multiple modules, and you can actually even add one more
by using the -i option. The dependencies are not tracked, so you should pass
inter-dependent modules in the right order.
I did not rebuild the whole tree, but the code passed both cstyle and lint checks,
and seems to work fine.
usr/src/cmd/modload/modunload.c | 94 ++++++++++++++++++++++++++++++++-------
1 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/usr/src/cmd/modload/modunload.c b/usr/src/cmd/modload/modunload.c
index f57a4b5..0451404 100644
--- a/usr/src/cmd/modload/modunload.c
+++ b/usr/src/cmd/modload/modunload.c
@@ -37,6 +37,8 @@
void usage();
void exec_userfile(char *execfile, int id, char **envp);
+int name_to_id(char *modname);
+void do_unload(int id, char *modname, char *exectfile, char *envp[]);
extern void fatal(char *fmt, ...);
extern void error(char *fmt, ...);
@@ -47,16 +49,12 @@ extern void error(char *fmt, ...);
int
main(int argc, char *argv[], char *envp[])
{
- int child;
- int status;
- int id;
+ int i;
+ int id = -1;
char *execfile = NULL;
int opt;
extern char *optarg;
- if (argc < 3)
- usage();
-
while ((opt = getopt(argc, argv, "i:e:")) != -1) {
switch (opt) {
case 'i':
@@ -72,6 +70,64 @@ main(int argc, char *argv[], char *envp[])
fatal("modunload can only be run from the global zone\n");
}
+ if (id >= 0) {
+ do_unload(id, NULL, execfile, envp);
+ } else if (optind >= argc) {
+ /* Eiter pass id with -i, or a module name as arg. Or both. */
+ usage();
+ }
+
+ /*
+ * If id is not specified explicitly, we loop over
+ * the given module names.
+ */
+ for (i = optind; i < argc; i++) {
+ id = name_to_id(argv[i]);
+ if (id < 0) {
+ fprintf(stderr, "Module '%s' not loaded\n", argv[i]);
+ continue;
+ }
+
+ do_unload(id, argv[i], execfile, envp);
+ }
+
+ return (0); /* success */
+}
+
+int
+name_to_id(char *modname)
+{
+ struct modinfo modinfo;
+ int id = -1;
+
+ modinfo.mi_id = modinfo.mi_nextid = id = -1;
+ modinfo.mi_info = MI_INFO_ALL | MI_INFO_CNT;
+
+ for (;;) {
+ if (modctl(MODINFO, id, &modinfo) < 0)
+ break;
+
+ id = modinfo.mi_id;
+
+ if (!(modinfo.mi_state & MI_LOADED))
+ continue;
+
+ if (!(strncmp(modinfo.mi_name, modname, MODMAXNAMELEN)))
+ return (id);
+ }
+
+ return (-1);
+}
+
+/*
+ * Unload a module. Optionally, run execfile.
+ */
+void
+do_unload(int id, char *modname, char *execfile, char *envp[])
+{
+ int child;
+ int status;
+
if (execfile) {
child = fork();
if (child == -1)
@@ -88,17 +144,22 @@ main(int argc, char *argv[], char *envp[])
}
}
- /*
- * Unload the module.
- */
if (modctl(MODUNLOAD, id) < 0) {
- if (errno == EPERM)
- fatal("Insufficient privileges to unload a module\n");
- else if (id != 0)
- error("can't unload the module");
+ if (errno == EPERM) {
+ fatal("Insufficient privileges to"
+ "unload a module\n");
+ } else if (id != 0) {
+ if (modname) {
+ fprintf(stderr,
+ "can't unload module '%s': %s\n",
+ modname, strerror(errno));
+ } else {
+ fprintf(stderr,
+ "can't unload module (id %d): %s\n",
+ id, strerror(errno));
+ }
+ }
}
-
- return (0); /* success */
}
/*
@@ -129,5 +190,6 @@ exec_userfile(char *execfile, int id, char **envp)
void
usage()
{
- fatal("usage: modunload -i <module_id> [-e <exec_file>]\n");
+ fatal("usage: modunload [-i <module_id>]"
+ "[-e <exec_file>] [module_name ... ]\n");
}
--
1.5.6.5
More information about the Developer
mailing list