diff --git a/src/dumm/irdumm.c b/src/dumm/irdumm.c index f468e7c79..d9437400a 100644 --- a/src/dumm/irdumm.c +++ b/src/dumm/irdumm.c @@ -194,13 +194,14 @@ static VALUE guest_exec(VALUE self, VALUE cmd) { guest_t *guest; bool block; + int ret; block = rb_block_given_p(); Data_Get_Struct(self, guest_t, guest); - if (guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL, - "%s", StringValuePtr(cmd)) != 0) + if ((ret = guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL, + "%s", StringValuePtr(cmd))) != 0) { - rb_raise(rb_eRuntimeError, "executing command failed"); + rb_raise(rb_eRuntimeError, "executing command failed (%d)", ret); } return self; } diff --git a/src/dumm/mconsole.c b/src/dumm/mconsole.c index b44a8e5e2..71062bedf 100644 --- a/src/dumm/mconsole.c +++ b/src/dumm/mconsole.c @@ -201,11 +201,7 @@ static bool del_iface(private_mconsole_t *this, char *guest) static int exec(private_mconsole_t *this, void(*cb)(void*,char*,size_t), void *data, char *cmd) { - if (request(this, cb, data, "exec %s", cmd) != 0) - { - return -1; - } - return 0; + return request(this, cb, data, "exec %s", cmd); } /** diff --git a/src/dumm/patches/mconsole-exec-2.6.26.patch b/src/dumm/patches/mconsole-exec-2.6.26.patch index 92601cfae..853b28f2a 100644 --- a/src/dumm/patches/mconsole-exec-2.6.26.patch +++ b/src/dumm/patches/mconsole-exec-2.6.26.patch @@ -1,5 +1,5 @@ --- a/arch/um/drivers/mconsole_kern.c 2008-07-13 23:51:29.000000000 +0200 -+++ b/arch/um/drivers/mconsole_kern.c 2008-07-15 15:41:54.000000000 +0200 ++++ b/arch/um/drivers/mconsole_kern.c 2008-07-31 14:04:57.000000000 +0200 @@ -4,6 +4,7 @@ * Licensed under the GPL */ @@ -8,20 +8,23 @@ #include #include #include -@@ -18,6 +19,7 @@ +@@ -18,6 +19,8 @@ #include #include #include ++#include +#include #include #include "init.h" -@@ -199,6 +201,44 @@ +@@ -199,6 +202,64 @@ } #endif +void mconsole_exec(struct mc_request *req) +{ ++ DECLARE_COMPLETION_ONSTACK(done); ++ struct subprocess_info *sub_info; + int res, len; + struct file *out; + char buf[MCONSOLE_MAX_DATA]; @@ -36,10 +39,24 @@ + req->request.data + strlen("exec "), + NULL + }; -+ res = call_usermodehelper_pipe("/bin/sh", argv, envp, NULL, &out); + ++ sub_info = call_usermodehelper_setup("/bin/sh", argv, envp); ++ if (sub_info == NULL) { ++ mconsole_reply(req, "call_usermodehelper_setup failed", 1, 0); ++ return; ++ } ++ res = call_usermodehelper_stdoutpipe(sub_info, &out); + if (res < 0) { -+ mconsole_reply(req, "call_usermodehelper_pipe failed", 1, 0); ++ call_usermodehelper_freeinfo(sub_info); ++ mconsole_reply(req, "call_usermodehelper_stdoutpipe failed", 1, 0); ++ return; ++ } ++ ++ call_usermodehelper_setcomplete(sub_info, &done); ++ ++ res = call_usermodehelper_exec(sub_info, UMH_WAIT_EXT); ++ if (res < 0) { ++ mconsole_reply(req, "call_usermodehelper_exec failed", 1, 0); + return; + } + @@ -49,19 +66,23 @@ + mconsole_reply(req, "reading output failed", 1, 0); + break; + } -+ if (len == 0) { -+ mconsole_reply_len(req, buf, len, 0, 0); ++ if (len == 0) + break; -+ } + mconsole_reply_len(req, buf, len, 0, 1); + } + fput(out); ++ ++ wait_for_completion(&done); ++ res = call_usermodehelper_getretval(sub_info) >> 8; ++ call_usermodehelper_freeinfo(sub_info); ++ ++ mconsole_reply_len(req, buf, len, res, 0); +} + void mconsole_proc(struct mc_request *req) { char path[64]; -@@ -270,6 +310,7 @@ +@@ -270,6 +331,7 @@ stop - pause the UML; it will do nothing until it receives a 'go' \n\ go - continue the UML after a 'stop' \n\ log - make UML enter into the kernel log\n\ @@ -90,8 +111,16 @@ extern void mconsole_stack(struct mc_request *req); --- a/kernel/kmod.c 2008-07-13 23:51:29.000000000 +0200 -+++ b/kernel/kmod.c 2008-07-15 15:41:54.000000000 +0200 -@@ -125,6 +125,7 @@ ++++ b/kernel/kmod.c 2008-07-31 14:46:31.000000000 +0200 +@@ -118,6 +118,7 @@ + struct subprocess_info { + struct work_struct work; + struct completion *complete; ++ struct completion *executed; + char *path; + char **argv; + char **envp; +@@ -125,6 +126,7 @@ enum umh_wait wait; int retval; struct file *stdin; @@ -99,7 +128,7 @@ void (*cleanup)(char **argv, char **envp); }; -@@ -160,8 +161,26 @@ +@@ -160,8 +162,26 @@ FD_SET(0, fdt->open_fds); FD_CLR(0, fdt->close_on_exec); spin_unlock(&f->file_lock); @@ -128,7 +157,53 @@ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; } -@@ -433,6 +452,29 @@ +@@ -243,7 +263,7 @@ + /* CLONE_VFORK: wait until the usermode helper has execve'd + * successfully We need the data structures to stay around + * until that is done. */ +- if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT) ++ if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT || wait == UMH_WAIT_EXT) + pid = kernel_thread(wait_for_helper, sub_info, + CLONE_FS | CLONE_FILES | SIGCHLD); + else +@@ -254,6 +274,16 @@ + case UMH_NO_WAIT: + break; + ++ case UMH_WAIT_EXT: ++ if (pid > 0) { ++ complete(sub_info->executed); ++ break; ++ } ++ sub_info->retval = pid; ++ complete(sub_info->executed); ++ complete(sub_info->complete); ++ break; ++ + case UMH_WAIT_PROC: + if (pid > 0) + break; +@@ -404,6 +434,19 @@ + } + EXPORT_SYMBOL(call_usermodehelper_setcleanup); + ++void call_usermodehelper_setcomplete(struct subprocess_info *info, ++ struct completion* complete) ++{ ++ info->complete = complete; ++} ++EXPORT_SYMBOL(call_usermodehelper_setcomplete); ++ ++int call_usermodehelper_getretval(struct subprocess_info *info) ++{ ++ return info->retval; ++} ++EXPORT_SYMBOL(call_usermodehelper_getretval); ++ + /** + * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin + * @sub_info: a subprocess_info returned by call_usermodehelper_setup +@@ -433,6 +476,29 @@ } EXPORT_SYMBOL(call_usermodehelper_stdinpipe); @@ -158,57 +233,62 @@ /** * call_usermodehelper_exec - start a usermode application * @sub_info: information about the subprocessa -@@ -489,7 +531,7 @@ - * lower-level call_usermodehelper_* functions. - */ - int call_usermodehelper_pipe(char *path, char **argv, char **envp, -- struct file **filp) -+ struct file **in, struct file **out) - { - struct subprocess_info *sub_info; - int ret; -@@ -498,9 +540,17 @@ - if (sub_info == NULL) - return -ENOMEM; +@@ -460,15 +526,22 @@ + goto out; + } -- ret = call_usermodehelper_stdinpipe(sub_info, filp); -- if (ret < 0) -- goto out; -+ if (in) { -+ ret = call_usermodehelper_stdinpipe(sub_info, in); -+ if (ret < 0) -+ goto out; -+ } +- sub_info->complete = &done; ++ if (wait == UMH_WAIT_EXT) ++ sub_info->executed = &done; ++ else ++ sub_info->complete = &done; + -+ if (out) { -+ ret = call_usermodehelper_stdoutpipe(sub_info, out); -+ if (ret < 0) -+ goto out; -+ } + sub_info->wait = wait; - return call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); + queue_work(khelper_wq, &sub_info->work); + if (wait == UMH_NO_WAIT) /* task has freed sub_info */ + goto unlock; ++ + wait_for_completion(&done); +- retval = sub_info->retval; ++ retval = sub_info->retval; ++ if (wait == UMH_WAIT_EXT) /* caller will free sub_info */ ++ goto unlock; + out: + call_usermodehelper_freeinfo(sub_info); + unlock: --- a/include/linux/kmod.h 2008-07-13 23:51:29.000000000 +0200 -+++ b/include/linux/kmod.h 2008-07-15 15:41:54.000000000 +0200 -@@ -93,6 +93,6 @@ - ++++ b/include/linux/kmod.h 2008-07-31 14:43:33.000000000 +0200 +@@ -38,6 +38,7 @@ + struct key; struct file; - extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[], -- struct file **filp); -+ struct file **in, struct file **out); + struct subprocess_info; ++struct completion; - #endif /* __LINUX_KMOD_H__ */ ---- a/fs/exec.c 2008-07-13 23:51:29.000000000 +0200 -+++ b/fs/exec.c 2008-07-15 15:41:54.000000000 +0200 -@@ -1741,7 +1741,7 @@ + /* Allocate a subprocess_info structure */ + struct subprocess_info *call_usermodehelper_setup(char *path, +@@ -48,13 +49,20 @@ + struct key *session_keyring); + int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, + struct file **filp); ++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, ++ struct file **filp); ++void call_usermodehelper_setcomplete(struct subprocess_info *sub_info, ++ struct completion *complete); + void call_usermodehelper_setcleanup(struct subprocess_info *info, + void (*cleanup)(char **argv, char **envp)); ++int call_usermodehelper_getretval(struct subprocess_info *sub_info); - /* SIGPIPE can happen, but it's just never processed */ - if (call_usermodehelper_pipe(corename+1, helper_argv, NULL, -- &file)) { -+ &file, NULL)) { - printk(KERN_INFO "Core dump to %s pipe failed\n", - corename); - goto fail_unlock; + 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 */ ++ UMH_WAIT_EXT = 2, /* wait for the exec then return and signal ++ when the process is complete */ + }; + + /* Actually execute the sub-process */ --- a/arch/um/Makefile 2008-07-13 23:51:29.000000000 +0200 +++ b/arch/um/Makefile 2008-07-15 16:27:02.000000000 +0200 @@ -77,6 +77,7 @@