Commit c4399016 authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

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: default avatarJeff Dike <jdike@linux.intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 42a359e3
...@@ -161,7 +161,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int init_aio_24(void) ...@@ -252,7 +252,6 @@ static int init_aio_24(void)
#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) ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, ...@@ -113,22 +109,21 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
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, ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ void maybe_sigio_broken(int fd, int read) ...@@ -356,10 +359,12 @@ void maybe_sigio_broken(int fd, int read)
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);
......
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