vserver 2.0-pre4
[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 siginfo info;
27         struct task_struct *p;
28         struct vx_info *vxi;
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         info.si_signo = vc_data.sig;
36         info.si_errno = 0;
37         info.si_code = SI_USER;
38         info.si_pid = current->pid;
39         info.si_uid = current->uid;
40
41         vxi = locate_vx_info(id);
42         if (!vxi)
43                 return -ESRCH;
44
45         retval = -ESRCH;
46         read_lock(&tasklist_lock);
47         switch (vc_data.pid) {
48         case  0:
49                 info.si_code = SI_KERNEL;
50         case -1:
51                 for_each_process(p) {
52                         int err = 0;
53
54                         if (vx_task_xid(p) != id || p->pid <= 1 ||
55                                 (vc_data.pid && vxi->vx_initpid == p->pid) ||
56                                 !thread_group_leader(p))
57                                 continue;
58
59                         err = send_sig_info(vc_data.sig, &info, p);
60                         ++count;
61                         if (err != -EPERM)
62                                 retval = err;
63                 }
64                 break;
65
66         case 1:
67                 if (vxi->vx_initpid) {
68                         vc_data.pid = vxi->vx_initpid;
69                         info.si_code = SI_KERNEL;
70                 }
71                 /* fallthrough */
72         default:
73                 p = find_task_by_real_pid(vc_data.pid);
74                 if (p) {
75                         if (!thread_group_leader(p)) {
76                                 struct task_struct *tg;
77
78                                 tg = find_task_by_real_pid(p->tgid);
79                                 if (tg)
80                                         p = tg;
81                         }
82                         if ((id == -1) || (vx_task_xid(p) == id))
83                                 retval = send_sig_info(vc_data.sig, &info, p);
84                 }
85                 break;
86         }
87         read_unlock(&tasklist_lock);
88         put_vx_info(vxi);
89         return retval;
90 }
91
92
93 static int __wait_exit(struct vx_info *vxi)
94 {
95         DECLARE_WAITQUEUE(wait, current);
96         int ret = 0;
97
98         add_wait_queue(&vxi->vx_wait, &wait);
99         set_current_state(TASK_INTERRUPTIBLE);
100
101 wait:
102         if (vx_info_state(vxi, VXS_SHUTDOWN|VXS_HASHED) == VXS_SHUTDOWN)
103                 goto out;
104         if (signal_pending(current)) {
105                 ret = -ERESTARTSYS;
106                 goto out;
107         }
108         schedule();
109         goto wait;
110
111 out:
112         set_current_state(TASK_RUNNING);
113         remove_wait_queue(&vxi->vx_wait, &wait);
114         return ret;
115 }
116
117
118
119 int vc_wait_exit(uint32_t id, void __user *data)
120 {
121 //      struct vcmd_wait_exit_v0 vc_data;
122         struct vx_info *vxi;
123         int ret;
124
125         vxi = locate_vx_info(id);
126         if (!vxi)
127                 return -ESRCH;
128
129         ret = __wait_exit(vxi);
130         put_vx_info(vxi);
131         return ret;
132 }
133