]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/kmod.c
kmod: add init function to usermodehelper
[net-next-2.6.git] / kernel / kmod.c
index bf0e231d970236278380019513b19188132bb62a..531ef62cf536711769e2dd1a2a1b7a5873d7a655 100644 (file)
@@ -116,27 +116,16 @@ int __request_module(bool wait, const char *fmt, ...)
 
        trace_module_request(module_name, wait, _RET_IP_);
 
-       ret = call_usermodehelper(modprobe_path, argv, envp,
-                       wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
+       ret = call_usermodehelper_fns(modprobe_path, argv, envp,
+                       wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC,
+                       NULL, NULL, NULL);
+
        atomic_dec(&kmod_concurrent);
        return ret;
 }
 EXPORT_SYMBOL(__request_module);
 #endif /* CONFIG_MODULES */
 
-struct subprocess_info {
-       struct work_struct work;
-       struct completion *complete;
-       struct cred *cred;
-       char *path;
-       char **argv;
-       char **envp;
-       enum umh_wait wait;
-       int retval;
-       struct file *stdin;
-       void (*cleanup)(char **argv, char **envp);
-};
-
 /*
  * This is the task which runs the usermode application
  */
@@ -184,9 +173,16 @@ static int ____call_usermodehelper(void *data)
         */
        set_user_nice(current, 0);
 
+       if (sub_info->init) {
+               retval = sub_info->init(sub_info);
+               if (retval)
+                       goto fail;
+       }
+
        retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp);
 
        /* Exec failed? */
+fail:
        sub_info->retval = retval;
        do_exit(0);
 }
@@ -194,7 +190,7 @@ static int ____call_usermodehelper(void *data)
 void call_usermodehelper_freeinfo(struct subprocess_info *info)
 {
        if (info->cleanup)
-               (*info->cleanup)(info->argv, info->envp);
+               (*info->cleanup)(info);
        if (info->cred)
                put_cred(info->cred);
        kfree(info);
@@ -406,21 +402,31 @@ void call_usermodehelper_setkeys(struct subprocess_info *info,
 EXPORT_SYMBOL(call_usermodehelper_setkeys);
 
 /**
- * call_usermodehelper_setcleanup - set a cleanup function
+ * call_usermodehelper_setfns - set a cleanup/init function
  * @info: a subprocess_info returned by call_usermodehelper_setup
  * @cleanup: a cleanup function
+ * @init: an init function
+ * @data: arbitrary context sensitive data
+ *
+ * The init function is used to customize the helper process prior to
+ * exec.  A non-zero return code causes the process to error out, exit,
+ * and return the failure to the calling process
  *
- * The cleanup function is just befor ethe subprocess_info is about to
+ * The cleanup function is just before ethe subprocess_info is about to
  * be freed.  This can be used for freeing the argv and envp.  The
  * Function must be runnable in either a process context or the
  * context in which call_usermodehelper_exec is called.
  */
-void call_usermodehelper_setcleanup(struct subprocess_info *info,
-                                   void (*cleanup)(char **argv, char **envp))
+void call_usermodehelper_setfns(struct subprocess_info *info,
+                   int (*init)(struct subprocess_info *info),
+                   void (*cleanup)(struct subprocess_info *info),
+                   void *data)
 {
        info->cleanup = cleanup;
+       info->init = init;
+       info->data = data;
 }
-EXPORT_SYMBOL(call_usermodehelper_setcleanup);
+EXPORT_SYMBOL(call_usermodehelper_setfns);
 
 /**
  * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
@@ -515,7 +521,8 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
        struct subprocess_info *sub_info;
        int ret;
 
-       sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL);
+       sub_info = call_usermodehelper_setup(path, argv, envp,
+                                            GFP_KERNEL);
        if (sub_info == NULL)
                return -ENOMEM;