diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-09-30 17:22:11 +0100 |
---|---|---|
committer | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-10-01 10:15:40 +0100 |
commit | a1babd3e7560d88209367bc7e3daa1cc43c96fcc (patch) | |
tree | a9ec03751cda20c389d831beaf37b9e985422ed4 | |
parent | 1743de8a7c10c10f9f9e34255bf737515794219c (diff) | |
download | module-init-tools-a1babd3e7560d88209367bc7e3daa1cc43c96fcc.tar.gz |
modprobe: Get module initstate from /proc/modules if not supported via sysfs
Apparently /sys/module/<module>/initstate only appeared in 2.6.20,
which is still in use.
Copy the original module_in_kernel() verbatim from the GIT archives,
and use it as a fallback if module_in_sysfs() doesn't work.
The original patch suggestion was shorter, but less obvious, adding
more untested code, and turned out to be harder to test.
References: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=524940
Reported-by: Matthew J. Lockner <mlockner@iastate.edu>
Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
-rw-r--r-- | modprobe.c | 76 |
1 files changed, 73 insertions, 3 deletions
@@ -519,6 +519,59 @@ static char *add_extra_options(const char *modname, return optstring; } +/* Is module in /proc/modules? If so, fill in usecount if not NULL. + 0 means no, 1 means yes, -1 means unknown. + */ +static int module_in_procfs(const char *modname, unsigned int *usecount) +{ + FILE *proc_modules; + char *line; + +again: + /* Might not be mounted yet. Don't fail. */ + proc_modules = fopen("/proc/modules", "r"); + if (!proc_modules) + return -1; + + while ((line = getline_wrapped(proc_modules, NULL)) != NULL) { + char *entry = strtok(line, " \n"); + + if (entry && streq(entry, modname)) { + /* If it exists, usecount is the third entry. */ + if (!strtok(NULL, " \n")) + goto out; + + if (!(entry = strtok(NULL, " \n"))) /* usecount */ + goto out; + else + if (usecount) + *usecount = atoi(entry); + + /* Followed by - then status. */ + if (strtok(NULL, " \n") + && (entry = strtok(NULL, " \n")) != NULL) { + /* No locking, we might hit cases + * where module is in flux. Spin. */ + if (streq(entry, "Loading") + || streq(entry, "Unloading")) { + usleep(100000); + free(line); + fclose(proc_modules); + goto again; + } + } + + out: + free(line); + fclose(proc_modules); + return 1; + } + free(line); + } + fclose(proc_modules); + return 0; +} + /* Read sysfs attribute into a buffer. * returns: 1 = ok, 0 = attribute missing, * -1 = file error (or empty file, but we don't care). @@ -537,10 +590,10 @@ static int read_attribute(const char *filename, char *buf, size_t buflen) return (s == NULL) ? -1 : 1; } -/* Is module in /sys/module? If so, fill in usecount if not NULL. +/* Is module in /sys/module? If so, fill in usecount if not NULL. 0 means no, 1 means yes, -1 means unknown. */ -static int module_in_kernel(const char *modname, unsigned int *usecount) +static int module_in_sysfs(const char *modname, unsigned int *usecount) { int ret; char *name; @@ -598,6 +651,22 @@ static int module_in_kernel(const char *modname, unsigned int *usecount) return 1; } +/* Is module loaded? If so, fill in usecount if not NULL. + 0 means no, 1 means yes, -1 means unknown. + */ +static int module_in_kernel(const char *modname, unsigned int *usecount) +{ + int result; + + result = module_in_sysfs(modname, usecount); + if (result != -1) + return result; + + /* /sys/module/%s/initstate is only available since 2.6.20, + fallback to /proc/modules to get module state on earlier kernels. */ + return module_in_procfs(modname, usecount); +} + void dump_modversions(const char *filename, errfn_t error) { struct elf_file *module; @@ -1146,7 +1215,8 @@ static int insmod(struct list_head *list, command = find_command(mod->modname, commands); if (command && !(flags & mit_ignore_commands)) { if (already_loaded == -1) { - warn("/sys/module/ not present.\n"); + warn("/sys/module/ not present or too old," + " and /proc/modules does not exist.\n"); warn("Ignoring install commands for %s" " in case it is already loaded.\n", newname ?: mod->modname); |