ceph: fix pr_fmt() redefinition
[deliverable/linux.git] / lib / kobject_uevent.c
index 5f72767ddd9b8471a5237a0b39ef0865e176934b..4e3bd71bd9495cfbf95fd9a28adf5e18a71f4592 100644 (file)
@@ -124,6 +124,30 @@ static int kobj_usermode_filter(struct kobject *kobj)
        return 0;
 }
 
+static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
+{
+       int len;
+
+       len = strlcpy(&env->buf[env->buflen], subsystem,
+                     sizeof(env->buf) - env->buflen);
+       if (len >= (sizeof(env->buf) - env->buflen)) {
+               WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
+               return -ENOMEM;
+       }
+
+       env->argv[0] = uevent_helper;
+       env->argv[1] = &env->buf[env->buflen];
+       env->argv[2] = NULL;
+
+       env->buflen += len + 1;
+       return 0;
+}
+
+static void cleanup_uevent_env(struct subprocess_info *info)
+{
+       kfree(info->data);
+}
+
 /**
  * kobject_uevent_env - send an uevent with environmental data
  *
@@ -301,11 +325,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 
        /* call uevent_helper, usually only enabled during early boot */
        if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
-               char *argv [3];
+               struct subprocess_info *info;
 
-               argv [0] = uevent_helper;
-               argv [1] = (char *)subsystem;
-               argv [2] = NULL;
                retval = add_uevent_var(env, "HOME=/");
                if (retval)
                        goto exit;
@@ -313,9 +334,18 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
                                        "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
                if (retval)
                        goto exit;
+               retval = init_uevent_argv(env, subsystem);
+               if (retval)
+                       goto exit;
 
-               retval = call_usermodehelper(argv[0], argv,
-                                            env->envp, UMH_WAIT_EXEC);
+               retval = -ENOMEM;
+               info = call_usermodehelper_setup(env->argv[0], env->argv,
+                                                env->envp, GFP_KERNEL,
+                                                NULL, cleanup_uevent_env, env);
+               if (info) {
+                       retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
+                       env = NULL;     /* freed by cleanup_uevent_env */
+               }
        }
 
 exit:
This page took 0.024409 seconds and 5 git commands to generate.