uml: simplify helper stack handling
run_helper and run_helper_thread had arguments which were the same in all callers. run_helper's stack_out was always NULL and run_helper_thread's stack_order was always 0. These are now gone, and the constants folded into the code. Also fixed leaks of the helper stack in the AIO and SIGIO code. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
42a359e31a
commit
c43990162f
|
@ -161,7 +161,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
|
||||||
* problem with /dev/net/tun, which if held open by this
|
* problem with /dev/net/tun, which if held open by this
|
||||||
* thread, prevents the TUN/TAP device from being reused.
|
* thread, prevents the TUN/TAP device from being reused.
|
||||||
*/
|
*/
|
||||||
err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out, 0);
|
err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
|
||||||
if(err < 0){
|
if(err < 0){
|
||||||
printk("fork of winch_thread failed - errno = %d\n", -err);
|
printk("fork of winch_thread failed - errno = %d\n", -err);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
|
|
|
@ -68,7 +68,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
|
||||||
args = pid_args;
|
args = pid_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = run_helper(pre_exec, &data, args, NULL);
|
pid = run_helper(pre_exec, &data, args);
|
||||||
|
|
||||||
os_close_file(out_fds[0]);
|
os_close_file(out_fds[0]);
|
||||||
os_close_file(in_fds[1]);
|
os_close_file(in_fds[1]);
|
||||||
|
|
|
@ -187,7 +187,7 @@ static int change_tramp(char **argv, char *output, int output_len)
|
||||||
}
|
}
|
||||||
pe_data.close_me = fds[0];
|
pe_data.close_me = fds[0];
|
||||||
pe_data.stdout = fds[1];
|
pe_data.stdout = fds[1];
|
||||||
pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
|
pid = run_helper(change_pre_exec, &pe_data, argv);
|
||||||
|
|
||||||
if (pid > 0) /* Avoid hang as we won't get data in failure case. */
|
if (pid > 0) /* Avoid hang as we won't get data in failure case. */
|
||||||
read_output(fds[0], output, output_len);
|
read_output(fds[0], output, output_len);
|
||||||
|
|
|
@ -188,7 +188,7 @@ int port_connection(int fd, int *socket, int *pid_out)
|
||||||
{ .sock_fd = new,
|
{ .sock_fd = new,
|
||||||
.pipe_fd = socket[1] });
|
.pipe_fd = socket[1] });
|
||||||
|
|
||||||
err = run_helper(port_pre_exec, &data, argv, NULL);
|
err = run_helper(port_pre_exec, &data, argv);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
goto out_shutdown;
|
goto out_shutdown;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ static int slip_tramp(char **argv, int fd)
|
||||||
pe_data.stdin = fd;
|
pe_data.stdin = fd;
|
||||||
pe_data.stdout = fds[1];
|
pe_data.stdout = fds[1];
|
||||||
pe_data.close_me = fds[0];
|
pe_data.close_me = fds[0];
|
||||||
err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
|
err = run_helper(slip_pre_exec, &pe_data, argv);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
pid = err;
|
pid = err;
|
||||||
|
|
|
@ -42,7 +42,7 @@ static int slirp_tramp(char **argv, int fd)
|
||||||
|
|
||||||
pe_data.stdin = fd;
|
pe_data.stdin = fd;
|
||||||
pe_data.stdout = fd;
|
pe_data.stdout = fd;
|
||||||
pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
|
pid = run_helper(slirp_pre_exec, &pe_data, argv);
|
||||||
|
|
||||||
return(pid);
|
return(pid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ static int xterm_open(int input, int output, int primary, void *d,
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(title, data->title, data->device);
|
sprintf(title, data->title, data->device);
|
||||||
pid = run_helper(NULL, NULL, argv, NULL);
|
pid = run_helper(NULL, NULL, argv);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
err = pid;
|
err = pid;
|
||||||
printk(UM_KERN_ERR "xterm_open : run_helper failed, "
|
printk(UM_KERN_ERR "xterm_open : run_helper failed, "
|
||||||
|
|
|
@ -239,11 +239,9 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n,
|
||||||
/* execvp.c */
|
/* execvp.c */
|
||||||
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
|
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
|
||||||
/* helper.c */
|
/* helper.c */
|
||||||
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
|
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
|
||||||
unsigned long *stack_out);
|
|
||||||
extern int run_helper_thread(int (*proc)(void *), void *arg,
|
extern int run_helper_thread(int (*proc)(void *), void *arg,
|
||||||
unsigned int flags, unsigned long *stack_out,
|
unsigned int flags, unsigned long *stack_out);
|
||||||
int stack_order);
|
|
||||||
extern int helper_wait(int pid);
|
extern int helper_wait(int pid);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@ static int do_not_aio(struct aio_thread_req *req)
|
||||||
static int aio_req_fd_r = -1;
|
static int aio_req_fd_r = -1;
|
||||||
static int aio_req_fd_w = -1;
|
static int aio_req_fd_w = -1;
|
||||||
static int aio_pid = -1;
|
static int aio_pid = -1;
|
||||||
|
static unsigned long aio_stack;
|
||||||
|
|
||||||
static int not_aio_thread(void *arg)
|
static int not_aio_thread(void *arg)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +213,6 @@ static int not_aio_thread(void *arg)
|
||||||
|
|
||||||
static int init_aio_24(void)
|
static int init_aio_24(void)
|
||||||
{
|
{
|
||||||
unsigned long stack;
|
|
||||||
int fds[2], err;
|
int fds[2], err;
|
||||||
|
|
||||||
err = os_pipe(fds, 1, 1);
|
err = os_pipe(fds, 1, 1);
|
||||||
|
@ -227,7 +227,7 @@ static int init_aio_24(void)
|
||||||
goto out_close_pipe;
|
goto out_close_pipe;
|
||||||
|
|
||||||
err = run_helper_thread(not_aio_thread, NULL,
|
err = run_helper_thread(not_aio_thread, NULL,
|
||||||
CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
|
CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
goto out_close_pipe;
|
goto out_close_pipe;
|
||||||
|
|
||||||
|
@ -252,7 +252,6 @@ out:
|
||||||
#define DEFAULT_24_AIO 0
|
#define DEFAULT_24_AIO 0
|
||||||
static int init_aio_26(void)
|
static int init_aio_26(void)
|
||||||
{
|
{
|
||||||
unsigned long stack;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if(io_setup(256, &ctx)){
|
if(io_setup(256, &ctx)){
|
||||||
|
@ -263,7 +262,7 @@ static int init_aio_26(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = run_helper_thread(aio_thread, NULL,
|
err = run_helper_thread(aio_thread, NULL,
|
||||||
CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
|
CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -365,8 +364,10 @@ __initcall(init_aio);
|
||||||
|
|
||||||
static void exit_aio(void)
|
static void exit_aio(void)
|
||||||
{
|
{
|
||||||
if(aio_pid != -1)
|
if (aio_pid != -1) {
|
||||||
os_kill_process(aio_pid, 1);
|
os_kill_process(aio_pid, 1);
|
||||||
|
free_stack(aio_stack, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__uml_exitcall(exit_aio);
|
__uml_exitcall(exit_aio);
|
||||||
|
|
|
@ -117,7 +117,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
|
||||||
pe_data.control_remote = control_remote;
|
pe_data.control_remote = control_remote;
|
||||||
pe_data.control_me = control_me;
|
pe_data.control_me = control_me;
|
||||||
pe_data.data_me = data_me;
|
pe_data.data_me = data_me;
|
||||||
pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
|
pid = run_helper(etap_pre_exec, &pe_data, args);
|
||||||
|
|
||||||
if(pid < 0)
|
if(pid < 0)
|
||||||
err = pid;
|
err = pid;
|
||||||
|
|
|
@ -83,7 +83,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
|
||||||
data.stdout = remote;
|
data.stdout = remote;
|
||||||
data.close_me = me;
|
data.close_me = me;
|
||||||
|
|
||||||
pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
|
pid = run_helper(tuntap_pre_exec, &data, argv);
|
||||||
|
|
||||||
if(pid < 0)
|
if(pid < 0)
|
||||||
return -pid;
|
return -pid;
|
||||||
|
|
|
@ -44,17 +44,13 @@ static int helper_child(void *arg)
|
||||||
/* Returns either the pid of the child process we run or -E* on failure.
|
/* Returns either the pid of the child process we run or -E* on failure.
|
||||||
* XXX The alloc_stack here breaks if this is called in the tracing thread, so
|
* XXX The alloc_stack here breaks if this is called in the tracing thread, so
|
||||||
* we need to receive a preallocated stack (a local buffer is ok). */
|
* we need to receive a preallocated stack (a local buffer is ok). */
|
||||||
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
|
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
|
||||||
unsigned long *stack_out)
|
|
||||||
{
|
{
|
||||||
struct helper_data data;
|
struct helper_data data;
|
||||||
unsigned long stack, sp;
|
unsigned long stack, sp;
|
||||||
int pid, fds[2], ret, n;
|
int pid, fds[2], ret, n;
|
||||||
|
|
||||||
if ((stack_out != NULL) && (*stack_out != 0))
|
stack = alloc_stack(0, __cant_sleep());
|
||||||
stack = *stack_out;
|
|
||||||
else
|
|
||||||
stack = alloc_stack(0, __cant_sleep());
|
|
||||||
if (stack == 0)
|
if (stack == 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -113,22 +109,21 @@ out_close:
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
out_free:
|
out_free:
|
||||||
if ((stack_out == NULL) || (*stack_out == 0))
|
free_stack(stack, 0);
|
||||||
free_stack(stack, 0);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
||||||
unsigned long *stack_out, int stack_order)
|
unsigned long *stack_out)
|
||||||
{
|
{
|
||||||
unsigned long stack, sp;
|
unsigned long stack, sp;
|
||||||
int pid, status, err;
|
int pid, status, err;
|
||||||
|
|
||||||
stack = alloc_stack(stack_order, __cant_sleep());
|
stack = alloc_stack(0, __cant_sleep());
|
||||||
if (stack == 0)
|
if (stack == 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
|
sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
|
||||||
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
|
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
|
@ -147,7 +142,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
||||||
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
|
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
|
||||||
printk("run_helper_thread - thread returned status "
|
printk("run_helper_thread - thread returned status "
|
||||||
"0x%x\n", status);
|
"0x%x\n", status);
|
||||||
free_stack(stack, stack_order);
|
free_stack(stack, 0);
|
||||||
} else
|
} else
|
||||||
*stack_out = stack;
|
*stack_out = stack;
|
||||||
return pid;
|
return pid;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* exitcall.
|
* exitcall.
|
||||||
*/
|
*/
|
||||||
static int write_sigio_pid = -1;
|
static int write_sigio_pid = -1;
|
||||||
|
static unsigned long write_sigio_stack;
|
||||||
|
|
||||||
/* These arrays are initialized before the sigio thread is started, and
|
/* These arrays are initialized before the sigio thread is started, and
|
||||||
* the descriptors closed after it is killed. So, it can't see them change.
|
* the descriptors closed after it is killed. So, it can't see them change.
|
||||||
|
@ -144,8 +145,10 @@ static void update_thread(void)
|
||||||
return;
|
return;
|
||||||
fail:
|
fail:
|
||||||
/* Critical section start */
|
/* Critical section start */
|
||||||
if(write_sigio_pid != -1)
|
if (write_sigio_pid != -1) {
|
||||||
os_kill_process(write_sigio_pid, 1);
|
os_kill_process(write_sigio_pid, 1);
|
||||||
|
free_stack(write_sigio_stack, 0);
|
||||||
|
}
|
||||||
write_sigio_pid = -1;
|
write_sigio_pid = -1;
|
||||||
close(sigio_private[0]);
|
close(sigio_private[0]);
|
||||||
close(sigio_private[1]);
|
close(sigio_private[1]);
|
||||||
|
@ -243,7 +246,6 @@ static struct pollfd *setup_initial_poll(int fd)
|
||||||
|
|
||||||
static void write_sigio_workaround(void)
|
static void write_sigio_workaround(void)
|
||||||
{
|
{
|
||||||
unsigned long stack;
|
|
||||||
struct pollfd *p;
|
struct pollfd *p;
|
||||||
int err;
|
int err;
|
||||||
int l_write_sigio_fds[2];
|
int l_write_sigio_fds[2];
|
||||||
|
@ -293,7 +295,8 @@ static void write_sigio_workaround(void)
|
||||||
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
|
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
|
||||||
|
|
||||||
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
||||||
CLONE_FILES | CLONE_VM, &stack, 0);
|
CLONE_FILES | CLONE_VM,
|
||||||
|
&write_sigio_stack);
|
||||||
|
|
||||||
if (write_sigio_pid < 0)
|
if (write_sigio_pid < 0)
|
||||||
goto out_clear;
|
goto out_clear;
|
||||||
|
@ -356,10 +359,12 @@ out:
|
||||||
|
|
||||||
static void sigio_cleanup(void)
|
static void sigio_cleanup(void)
|
||||||
{
|
{
|
||||||
if(write_sigio_pid != -1){
|
if (write_sigio_pid == -1)
|
||||||
os_kill_process(write_sigio_pid, 1);
|
return;
|
||||||
write_sigio_pid = -1;
|
|
||||||
}
|
os_kill_process(write_sigio_pid, 1);
|
||||||
|
free_stack(write_sigio_stack, 0);
|
||||||
|
write_sigio_pid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__uml_exitcall(sigio_cleanup);
|
__uml_exitcall(sigio_cleanup);
|
||||||
|
|
Loading…
Reference in New Issue