vserver 2.0-rc4
[linux-2.6.git] / kernel / vserver / signal.c
1 /*
2  *  linux/kernel/vserver/signal.c
3  *
4  *  Virtual Server: Signal Support
5  *
6  *  Copyright (C) 2003-2005  Herbert Pƶtzl
7  *
8  *  V0.01  broken out from vcontext V0.05
9  *
10  */
11
12 #include <linux/config.h>
13 #include <linux/sched.h>
14
15 #include <asm/errno.h>
16 #include <asm/uaccess.h>
17
18 #include <linux/vs_context.h>
19 #include <linux/vserver/signal_cmd.h>
20
21
22 int vc_ctx_kill(uint32_t id, void __user *data)
23 {
24         int retval, count=0;
25         struct vcmd_ctx_kill_v0 vc_data;
26         struct task_struct *p;
27         struct vx_info *vxi;
28         unsigned long priv = 0;
29
30         if (!vx_check(0, VX_ADMIN))
31                 return -ENOSYS;
32         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
33                 return -EFAULT;
34
35         vxi = locate_vx_info(id);
36         if (!vxi)
37                 return -ESRCH;
38
39         retval = -ESRCH;
40         read_lock(&tasklist_lock);
41         switch (vc_data.pid) {
42         case  0:
43                 priv = 1;
44         case -1:
45                 for_each_process(p) {
46                         int err = 0;
47
48                         if (vx_task_xid(p) != id || p->pid <= 1 ||
49                                 (vc_data.pid && vxi->vx_initpid == p->pid))
50                                 continue;
51
52                         err = group_send_sig_info(vc_data.sig, (void*)priv, p);
53                         ++count;
54                         if (err != -EPERM)
55                                 retval = err;
56                 }
57                 break;
58
59         case 1:
60                 if (vxi->vx_initpid) {
61                         vc_data.pid = vxi->vx_initpid;
62                         priv = 1;
63                 }
64                 /* fallthrough */
65         default:
66                 p = find_task_by_real_pid(vc_data.pid);
67                 if (p) {
68                         if ((id == -1) || (vx_task_xid(p) == id))
69                                 retval = group_send_sig_info(vc_data.sig,
70                                         (void*)priv, p);
71                 }
72                 break;
73         }
74         read_unlock(&tasklist_lock);
75         put_vx_info(vxi);
76         return retval;
77 }
78
79
80 static int __wait_exit(struct vx_info *vxi)
81 {
82         DECLARE_WAITQUEUE(wait, current);
83         int ret = 0;
84
85         add_wait_queue(&vxi->vx_wait, &wait);
86         set_current_state(TASK_INTERRUPTIBLE);
87
88 wait:
89         if (vx_info_state(vxi, VXS_SHUTDOWN|VXS_HASHED) == VXS_SHUTDOWN)
90                 goto out;
91         if (signal_pending(current)) {
92                 ret = -ERESTARTSYS;
93                 goto out;
94         }
95         schedule();
96         goto wait;
97
98 out:
99         set_current_state(TASK_RUNNING);
100         remove_wait_queue(&vxi->vx_wait, &wait);
101         return ret;
102 }
103
104
105
106 int vc_wait_exit(uint32_t id, void __user *data)
107 {
108         struct vx_info *vxi;
109         int ret;
110
111         vxi = locate_vx_info(id);
112         if (!vxi)
113                 return -ESRCH;
114
115         ret = __wait_exit(vxi);
116         put_vx_info(vxi);
117         return ret;
118 }
119