X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fvserver%2Fsignal.c;h=b11a3a3585e8d6e77c64cc69e1d1cf278644113e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=200eba83a0074aa8548df60b6c365c03cf739461;hpb=d46bc780027c5439db9f72d42c0732775b53925a;p=linux-2.6.git diff --git a/kernel/vserver/signal.c b/kernel/vserver/signal.c index 200eba83a..b11a3a358 100644 --- a/kernel/vserver/signal.c +++ b/kernel/vserver/signal.c @@ -3,83 +3,137 @@ * * Virtual Server: Signal Support * - * Copyright (C) 2003-2004 Herbert Pötzl + * Copyright (C) 2003-2005 Herbert Pötzl * * V0.01 broken out from vcontext V0.05 * */ -#include #include #include #include -#include -#include +#include +#include -int vc_ctx_kill(uint32_t id, void __user *data) +int vx_info_kill(struct vx_info *vxi, int pid, int sig) { int retval, count=0; - struct vcmd_ctx_kill_v0 vc_data; - struct siginfo info; struct task_struct *p; - struct vx_info *vxi; - - if (!vx_check(0, VX_ADMIN)) - return -ENOSYS; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) - return -EFAULT; - - info.si_signo = vc_data.sig; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->pid; - info.si_uid = current->uid; - - vxi = locate_vx_info(id); - if (!vxi) - return -ESRCH; + unsigned long priv = 0; retval = -ESRCH; + vxdprintk(VXD_CBIT(misc, 4), + "vx_info_kill(%p[#%d],%d,%d)*", + vxi, vxi->vx_id, pid, sig); read_lock(&tasklist_lock); - switch (vc_data.pid) { - case -1: + switch (pid) { case 0: + priv = 1; + case -1: for_each_process(p) { int err = 0; - if (vx_task_xid(p) != id || p->pid <= 1 || - (vc_data.pid && vxi->vx_initpid == p->pid) || - !thread_group_leader(p)) + if (vx_task_xid(p) != vxi->vx_id || p->pid <= 1 || + (pid && vxi->vx_initpid == p->pid)) continue; - err = send_sig_info(vc_data.sig, &info, p); + err = group_send_sig_info(sig, (void*)priv, p); ++count; if (err != -EPERM) retval = err; } break; - + + case 1: + if (vxi->vx_initpid) { + pid = vxi->vx_initpid; + priv = 1; + } + /* fallthrough */ default: - p = find_task_by_pid(vc_data.pid); + p = find_task_by_real_pid(pid); if (p) { - if (!thread_group_leader(p)) { - struct task_struct *tg; - - tg = find_task_by_pid(p->tgid); - if (tg) - p = tg; - } - if ((id == -1) || (vx_task_xid(p) == id)) - retval = send_sig_info(vc_data.sig, &info, p); + if (vx_task_xid(p) == vxi->vx_id) + retval = group_send_sig_info(sig, + (void*)priv, p); } break; } read_unlock(&tasklist_lock); + vxdprintk(VXD_CBIT(misc, 4), + "vx_info_kill(%p[#%d],%d,%d) = %d", + vxi, vxi->vx_id, pid, sig, retval); + return retval; +} + +int vc_ctx_kill(uint32_t id, void __user *data) +{ + int retval; + struct vcmd_ctx_kill_v0 vc_data; + struct vx_info *vxi; + + if (!vx_check(0, VX_ADMIN)) + return -ENOSYS; + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + retval = vx_info_kill(vxi, vc_data.pid, vc_data.sig); put_vx_info(vxi); return retval; } +static int __wait_exit(struct vx_info *vxi) +{ + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + add_wait_queue(&vxi->vx_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + +wait: + if (vx_info_state(vxi, + VXS_SHUTDOWN|VXS_HASHED|VXS_HELPER) == VXS_SHUTDOWN) + goto out; + if (signal_pending(current)) { + ret = -ERESTARTSYS; + goto out; + } + schedule(); + goto wait; + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&vxi->vx_wait, &wait); + return ret; +} + + + +int vc_wait_exit(uint32_t id, void __user *data) +{ + struct vx_info *vxi; + struct vcmd_wait_exit_v0 vc_data; + int ret; + + vxi = lookup_vx_info(id); + if (!vxi) + return -ESRCH; + + ret = __wait_exit(vxi); + vc_data.reboot_cmd = vxi->reboot_cmd; + vc_data.exit_code = vxi->exit_code; + put_vx_info(vxi); + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} +