[PATCH][RFC] __request_module: fixed argument request_module with waitflag

Per Svennerbrandt
2005-05-18T23:01:52Z

The following extracts the code in request_module which is responsible
for executing modprobe into a new helper function called __request_module.
This new function takes the wait flag which gets passed down to
call_usermodeheper as an argument, allowing async execution of modprobe.

During the writing of this I've had a bit of a mental struggle about
whether or not maybe call_modprobe is a better name for this and thus
I'm fine with either one if anyone else has a preference.

Signed-off-by: Per Svennerbrandt <per.svennerbrandt@lbi.se>

--- linux-2.6.12-rc2/kernel/kmod.c.orig 2005-04-16 19:08:22.000000000 +0200
+++ linux-2.6.12-rc2/kernel/kmod.c 2005-05-12 23:50:00.000000000 +0200
@@ -49,6 +49,49 @@
*/
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";

+int __request_module(char *name, int wait)
+{
+ int ret;
+ unsigned int max_modprobes;
+ static atomic_t kmod_concurrent = ATOMIC_INIT(0);
+#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
+ static int kmod_loop_msg;
+
+ char *argv[] = { modprobe_path, "-q", "--", name, NULL };
+ static char *envp[] = { "HOME=/",
+ "TERM=linux",
+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+ NULL };
+
+ /* If modprobe needs a service that is in a module, we get a recursive
+ * loop. Limit the number of running kmod threads to max_threads/2 or
+ * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
+ * would be to run the parents of this process, counting how many times
+ * kmod was invoked. That would mean accessing the internals of the
+ * process tables to get the command line, proc_pid_cmdline is static
+ * and it is not worth changing the proc code just to handle this case.
+ * KAO.
+ *
+ * "trace the ppid" is simple, but will fail if someone's
+ * parent exits. I think this is as good as it gets. --RR
+ */
+ max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
+ atomic_inc(&kmod_concurrent);
+ if (atomic_read(&kmod_concurrent) > max_modprobes) {
+ /* We may be blaming an innocent here, but unlikely */
+ if (kmod_loop_msg++ < 5)
+ printk(KERN_ERR
+ "request_module: runaway loop modprobe %s\n",
+ name);
+ atomic_dec(&kmod_concurrent);
+ return -ENOMEM;
+ }
+ ret = call_usermodehelper(modprobe_path, argv, envp, wait);
+ atomic_dec(&kmod_concurrent);
+ return ret;
+}
+EXPORT_SYMBOL(__request_module);
+
/**
* request_module - try to load a kernel module
* @fmt: printf style format string for the name of the module
@@ -67,50 +110,15 @@ int request_module(const char *fmt, ...)
{
va_list args;
char module_name[MODULE_NAME_LEN];
- unsigned int max_modprobes;
int ret;
- char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
- static char *envp[] = { "HOME=/",
- "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
- NULL };
- static atomic_t kmod_concurrent = ATOMIC_INIT(0);
-#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
- static int kmod_loop_msg;

va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;

- /* If modprobe needs a service that is in a module, we get a recursive
- * loop. Limit the number of running kmod threads to max_threads/2 or
- * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
- * would be to run the parents of this process, counting how many times
- * kmod was invoked. That would mean accessing the internals of the
- * process tables to get the command line, proc_pid_cmdline is static
- * and it is not worth changing the proc code just to handle this case.
- * KAO.
- *
- * "trace the ppid" is simple, but will fail if someone's
- * parent exits. I think this is as good as it gets. --RR
- */
- max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
- atomic_inc(&kmod_concurrent);
- if (atomic_read(&kmod_concurrent) > max_modprobes) {
- /* We may be blaming an innocent here, but unlikely */
- if (kmod_loop_msg++ < 5)
- printk(KERN_ERR
- "request_module: runaway loop modprobe %s\n",
- module_name);
- atomic_dec(&kmod_concurrent);
- return -ENOMEM;
- }
-
- ret = call_usermodehelper(modprobe_path, argv, envp, 1);
- atomic_dec(&kmod_concurrent);
- return ret;
+ return __request_module(module_name, 1);
}
EXPORT_SYMBOL(request_module);
#endif /* CONFIG_KMOD */
--- linux-2.6.12-rc2/include/linux/kmod.h.orig 2005-03-02 08:37:49.000000000 +0100
+++ linux-2.6.12-rc2/include/linux/kmod.h 2005-05-12 23:53:22.000000000 +0200
@@ -28,8 +28,10 @@
#ifdef CONFIG_KMOD
/* modprobe exit status on success, -ve on error. Return value
* usually useless though. */
+extern int __request_module(char *name, int wait);
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
#else
+static inline int __request_module(char *name, int wait) { return -ENOSYS; }
static inline int request_module(const char * name, ...) { return -ENOSYS; }
#endif