aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2009-09-30 17:22:11 +0100
committerAlan Jenkins <alan-jenkins@tuffmail.co.uk>2009-10-01 10:15:40 +0100
commita1babd3e7560d88209367bc7e3daa1cc43c96fcc (patch)
treea9ec03751cda20c389d831beaf37b9e985422ed4
parent1743de8a7c10c10f9f9e34255bf737515794219c (diff)
downloadmodule-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.c76
1 files changed, 73 insertions, 3 deletions
diff --git a/modprobe.c b/modprobe.c
index 2b45510..e6fad70 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -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);