Commit 86313c48 authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Jeremy Fitzhardinge

usermodehelper: Tidy up waiting

Rather than using a tri-state integer for the wait flag in
call_usermodehelper_exec, define a proper enum, and use that.  I've
preserved the integer values so that any callers I've missed should
still work OK.
Signed-off-by: default avatarJeremy Fitzhardinge <jeremy@xensource.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Andi Kleen <ak@suse.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Joel Becker <joel.becker@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Cc: David Howells <dhowells@redhat.com>
parent 10a0a8d4
...@@ -52,7 +52,7 @@ execute(const char *string) ...@@ -52,7 +52,7 @@ execute(const char *string)
NULL, NULL,
}; };
if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) { if ((ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) {
printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", printk(KERN_ERR "Voyager failed to run \"%s\": %i\n",
string, ret); string, ret);
} }
......
...@@ -174,7 +174,7 @@ static void do_mce_trigger(void) ...@@ -174,7 +174,7 @@ static void do_mce_trigger(void)
if (events != atomic_read(&mce_logged) && trigger[0]) { if (events != atomic_read(&mce_logged) && trigger[0]) {
/* Small race window, but should be harmless. */ /* Small race window, but should be harmless. */
atomic_set(&mce_logged, events); atomic_set(&mce_logged, events);
call_usermodehelper(trigger, trigger_argv, NULL, -1); call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
} }
} }
......
...@@ -1770,7 +1770,8 @@ static int call_critical_overtemp(void) ...@@ -1770,7 +1770,8 @@ static int call_critical_overtemp(void)
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL }; NULL };
return call_usermodehelper(critical_overtemp_path, argv, envp, 0); return call_usermodehelper(critical_overtemp_path,
argv, envp, UMH_WAIT_EXEC);
} }
......
...@@ -80,7 +80,8 @@ int wf_critical_overtemp(void) ...@@ -80,7 +80,8 @@ int wf_critical_overtemp(void)
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL }; NULL };
return call_usermodehelper(critical_overtemp_path, argv, envp, 0); return call_usermodehelper(critical_overtemp_path,
argv, envp, UMH_WAIT_EXEC);
} }
EXPORT_SYMBOL_GPL(wf_critical_overtemp); EXPORT_SYMBOL_GPL(wf_critical_overtemp);
......
...@@ -320,7 +320,7 @@ static int eppconfig(struct baycom_state *bc) ...@@ -320,7 +320,7 @@ static int eppconfig(struct baycom_state *bc)
sprintf(portarg, "%ld", bc->pdev->port->base); sprintf(portarg, "%ld", bc->pdev->port->base);
printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg); printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
return call_usermodehelper(eppconfig_path, argv, envp, 1); return call_usermodehelper(eppconfig_path, argv, envp, UMH_WAIT_PROC);
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
......
...@@ -147,7 +147,7 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) ...@@ -147,7 +147,7 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
info->location_id, info->serial, info->capabilities); info->location_id, info->serial, info->capabilities);
envp[i] = NULL; envp[i] = NULL;
value = call_usermodehelper (argv [0], argv, envp, 0); value = call_usermodehelper (argv [0], argv, envp, UMH_WAIT_EXEC);
kfree (buf); kfree (buf);
kfree (envp); kfree (envp);
return 0; return 0;
......
...@@ -209,7 +209,7 @@ void ocfs2_stop_heartbeat(struct ocfs2_super *osb) ...@@ -209,7 +209,7 @@ void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp[2] = NULL; envp[2] = NULL;
ret = call_usermodehelper(argv[0], argv, envp, 1); ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
if (ret < 0) if (ret < 0)
mlog_errno(ret); mlog_errno(ret);
} }
......
...@@ -51,15 +51,21 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, ...@@ -51,15 +51,21 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
void call_usermodehelper_setcleanup(struct subprocess_info *info, void call_usermodehelper_setcleanup(struct subprocess_info *info,
void (*cleanup)(char **argv, char **envp)); void (*cleanup)(char **argv, char **envp));
enum umh_wait {
UMH_NO_WAIT = -1, /* don't wait at all */
UMH_WAIT_EXEC = 0, /* wait for the exec, but not the process */
UMH_WAIT_PROC = 1, /* wait for the process to complete */
};
/* Actually execute the sub-process */ /* Actually execute the sub-process */
int call_usermodehelper_exec(struct subprocess_info *info, int wait); int call_usermodehelper_exec(struct subprocess_info *info, enum umh_wait wait);
/* Free the subprocess_info. This is only needed if you're not going /* Free the subprocess_info. This is only needed if you're not going
to call call_usermodehelper_exec */ to call call_usermodehelper_exec */
void call_usermodehelper_freeinfo(struct subprocess_info *info); void call_usermodehelper_freeinfo(struct subprocess_info *info);
static inline int static inline int
call_usermodehelper(char *path, char **argv, char **envp, int wait) call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
{ {
struct subprocess_info *info; struct subprocess_info *info;
...@@ -71,7 +77,7 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait) ...@@ -71,7 +77,7 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait)
static inline int static inline int
call_usermodehelper_keys(char *path, char **argv, char **envp, call_usermodehelper_keys(char *path, char **argv, char **envp,
struct key *session_keyring, int wait) struct key *session_keyring, enum umh_wait wait)
{ {
struct subprocess_info *info; struct subprocess_info *info;
......
...@@ -516,7 +516,7 @@ static void cpuset_release_agent(const char *pathbuf) ...@@ -516,7 +516,7 @@ static void cpuset_release_agent(const char *pathbuf)
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp[i] = NULL; envp[i] = NULL;
call_usermodehelper(argv[0], argv, envp, 0); call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
kfree(pathbuf); kfree(pathbuf);
} }
......
...@@ -119,7 +119,7 @@ struct subprocess_info { ...@@ -119,7 +119,7 @@ struct subprocess_info {
char **argv; char **argv;
char **envp; char **envp;
struct key *ring; struct key *ring;
int wait; enum umh_wait wait;
int retval; int retval;
struct file *stdin; struct file *stdin;
void (*cleanup)(char **argv, char **envp); void (*cleanup)(char **argv, char **envp);
...@@ -225,7 +225,7 @@ static int wait_for_helper(void *data) ...@@ -225,7 +225,7 @@ static int wait_for_helper(void *data)
sub_info->retval = ret; sub_info->retval = ret;
} }
if (sub_info->wait < 0) if (sub_info->wait == UMH_NO_WAIT)
call_usermodehelper_freeinfo(sub_info); call_usermodehelper_freeinfo(sub_info);
else else
complete(sub_info->complete); complete(sub_info->complete);
...@@ -238,26 +238,31 @@ static void __call_usermodehelper(struct work_struct *work) ...@@ -238,26 +238,31 @@ static void __call_usermodehelper(struct work_struct *work)
struct subprocess_info *sub_info = struct subprocess_info *sub_info =
container_of(work, struct subprocess_info, work); container_of(work, struct subprocess_info, work);
pid_t pid; pid_t pid;
int wait = sub_info->wait; enum umh_wait wait = sub_info->wait;
/* CLONE_VFORK: wait until the usermode helper has execve'd /* CLONE_VFORK: wait until the usermode helper has execve'd
* successfully We need the data structures to stay around * successfully We need the data structures to stay around
* until that is done. */ * until that is done. */
if (wait) if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT)
pid = kernel_thread(wait_for_helper, sub_info, pid = kernel_thread(wait_for_helper, sub_info,
CLONE_FS | CLONE_FILES | SIGCHLD); CLONE_FS | CLONE_FILES | SIGCHLD);
else else
pid = kernel_thread(____call_usermodehelper, sub_info, pid = kernel_thread(____call_usermodehelper, sub_info,
CLONE_VFORK | SIGCHLD); CLONE_VFORK | SIGCHLD);
if (wait < 0) switch (wait) {
return; case UMH_NO_WAIT:
break;
if (pid < 0) { case UMH_WAIT_PROC:
if (pid > 0)
break;
sub_info->retval = pid; sub_info->retval = pid;
/* FALLTHROUGH */
case UMH_WAIT_EXEC:
complete(sub_info->complete); complete(sub_info->complete);
} else if (!wait) }
complete(sub_info->complete);
} }
/** /**
...@@ -359,7 +364,7 @@ EXPORT_SYMBOL(call_usermodehelper_stdinpipe); ...@@ -359,7 +364,7 @@ EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
* (ie. it runs with full root capabilities). * (ie. it runs with full root capabilities).
*/ */
int call_usermodehelper_exec(struct subprocess_info *sub_info, int call_usermodehelper_exec(struct subprocess_info *sub_info,
int wait) enum umh_wait wait)
{ {
DECLARE_COMPLETION_ONSTACK(done); DECLARE_COMPLETION_ONSTACK(done);
int retval; int retval;
...@@ -378,7 +383,7 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, ...@@ -378,7 +383,7 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
sub_info->wait = wait; sub_info->wait = wait;
queue_work(khelper_wq, &sub_info->work); queue_work(khelper_wq, &sub_info->work);
if (wait < 0) /* task has freed sub_info */ if (wait == UMH_NO_WAIT) /* task has freed sub_info */
return 0; return 0;
wait_for_completion(&done); wait_for_completion(&done);
retval = sub_info->retval; retval = sub_info->retval;
......
...@@ -2327,7 +2327,7 @@ int orderly_poweroff(bool force) ...@@ -2327,7 +2327,7 @@ int orderly_poweroff(bool force)
call_usermodehelper_setcleanup(info, argv_cleanup); call_usermodehelper_setcleanup(info, argv_cleanup);
ret = call_usermodehelper_exec(info, -1); ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
out: out:
if (ret && force) { if (ret && force) {
......
...@@ -208,7 +208,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, ...@@ -208,7 +208,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
argv [0] = uevent_helper; argv [0] = uevent_helper;
argv [1] = (char *)subsystem; argv [1] = (char *)subsystem;
argv [2] = NULL; argv [2] = NULL;
call_usermodehelper (argv[0], argv, envp, 0); call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC);
} }
exit: exit:
......
...@@ -125,7 +125,7 @@ static void br_stp_start(struct net_bridge *br) ...@@ -125,7 +125,7 @@ static void br_stp_start(struct net_bridge *br)
char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
char *envp[] = { NULL }; char *envp[] = { NULL };
r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
if (r == 0) { if (r == 0) {
br->stp_enabled = BR_USER_STP; br->stp_enabled = BR_USER_STP;
printk(KERN_INFO "%s: userspace STP started\n", br->dev->name); printk(KERN_INFO "%s: userspace STP started\n", br->dev->name);
......
...@@ -108,7 +108,8 @@ static int call_sbin_request_key(struct key *key, ...@@ -108,7 +108,8 @@ static int call_sbin_request_key(struct key *key,
argv[i] = NULL; argv[i] = NULL;
/* do it */ /* do it */
ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1); ret = call_usermodehelper_keys(argv[0], argv, envp, keyring,
UMH_WAIT_PROC);
error_link: error_link:
key_put(keyring); key_put(keyring);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment