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: Jeremy 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>
This commit is contained in:
parent
10a0a8d4e3
commit
86313c488a
|
@ -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)
|
||||||
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)
|
||||||
"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)
|
||||||
"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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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 {
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
* (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,
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue