Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / kernel / vserver / context.c
1 /*
2  *  linux/kernel/vserver/context.c
3  *
4  *  Virtual Server: Context Support
5  *
6  *  Copyright (C) 2003-2005  Herbert Pƶtzl
7  *
8  *  V0.01  context helper
9  *  V0.02  vx_ctx_kill syscall command
10  *  V0.03  replaced context_info calls
11  *  V0.04  redesign of struct (de)alloc
12  *  V0.05  rlimit basic implementation
13  *  V0.06  task_xid and info commands
14  *  V0.07  context flags and caps
15  *  V0.08  switch to RCU based hash
16  *  V0.09  revert to non RCU for now
17  *  V0.10  and back to working RCU hash
18  *  V0.11  and back to locking again
19  *
20  */
21
22 #include <linux/slab.h>
23 #include <linux/types.h>
24 #include <linux/namespace.h>
25
26 #include <linux/sched.h>
27 #include <linux/vserver/network.h>
28 #include <linux/vserver/legacy.h>
29 #include <linux/vserver/limit.h>
30 #include <linux/vserver/debug.h>
31 #include <linux/vserver/limit_int.h>
32
33 #include <linux/vs_context.h>
34 #include <linux/vs_limit.h>
35 #include <linux/vserver/context_cmd.h>
36
37 #include <linux/err.h>
38 #include <asm/errno.h>
39
40 #include "cvirt_init.h"
41 #include "limit_init.h"
42 #include "sched_init.h"
43
44
45 /*      __alloc_vx_info()
46
47         * allocate an initialized vx_info struct
48         * doesn't make it visible (hash)                        */
49
50 static struct vx_info *__alloc_vx_info(xid_t xid)
51 {
52         struct vx_info *new = NULL;
53
54         vxdprintk(VXD_CBIT(xid, 0), "alloc_vx_info(%d)*", xid);
55
56         /* would this benefit from a slab cache? */
57         new = kmalloc(sizeof(struct vx_info), GFP_KERNEL);
58         if (!new)
59                 return 0;
60
61         memset (new, 0, sizeof(struct vx_info));
62         new->vx_id = xid;
63         INIT_HLIST_NODE(&new->vx_hlist);
64         atomic_set(&new->vx_usecnt, 0);
65         atomic_set(&new->vx_tasks, 0);
66         new->vx_parent = NULL;
67         new->vx_state = 0;
68         init_waitqueue_head(&new->vx_wait);
69
70         /* prepare reaper */
71         get_task_struct(child_reaper);
72         new->vx_reaper = child_reaper;
73
74         /* rest of init goes here */
75         vx_info_init_limit(&new->limit);
76         vx_info_init_sched(&new->sched);
77         vx_info_init_cvirt(&new->cvirt);
78         vx_info_init_cacct(&new->cacct);
79
80         new->vx_flags = VXF_INIT_SET;
81         new->vx_bcaps = CAP_INIT_EFF_SET;
82         new->vx_ccaps = 0;
83
84         new->reboot_cmd = 0;
85         new->exit_code = 0;
86
87         vxdprintk(VXD_CBIT(xid, 0),
88                 "alloc_vx_info(%d) = %p", xid, new);
89         vxh_alloc_vx_info(new);
90         return new;
91 }
92
93 /*      __dealloc_vx_info()
94
95         * final disposal of vx_info                             */
96
97 static void __dealloc_vx_info(struct vx_info *vxi)
98 {
99         vxdprintk(VXD_CBIT(xid, 0),
100                 "dealloc_vx_info(%p)", vxi);
101         vxh_dealloc_vx_info(vxi);
102
103         vxi->vx_hlist.next = LIST_POISON1;
104         vxi->vx_id = -1;
105
106         vx_info_exit_limit(&vxi->limit);
107         vx_info_exit_sched(&vxi->sched);
108         vx_info_exit_cvirt(&vxi->cvirt);
109         vx_info_exit_cacct(&vxi->cacct);
110
111         vxi->vx_state |= VXS_RELEASED;
112         kfree(vxi);
113 }
114
115 static void __shutdown_vx_info(struct vx_info *vxi)
116 {
117         struct namespace *namespace;
118         struct fs_struct *fs;
119
120         might_sleep();
121
122         vxi->vx_state |= VXS_SHUTDOWN;
123         vs_state_change(vxi, VSC_SHUTDOWN);
124
125         namespace = xchg(&vxi->vx_namespace, NULL);
126         if (namespace)
127                 put_namespace(namespace);
128
129         fs = xchg(&vxi->vx_fs, NULL);
130         if (fs)
131                 put_fs_struct(fs);
132 }
133
134 /* exported stuff */
135
136 void free_vx_info(struct vx_info *vxi)
137 {
138         /* context shutdown is mandatory */
139         BUG_ON(!vx_info_state(vxi, VXS_SHUTDOWN));
140
141         BUG_ON(atomic_read(&vxi->vx_usecnt));
142         BUG_ON(atomic_read(&vxi->vx_tasks));
143
144         BUG_ON(vx_info_state(vxi, VXS_HASHED));
145
146         BUG_ON(vxi->vx_namespace);
147         BUG_ON(vxi->vx_fs);
148
149         __dealloc_vx_info(vxi);
150 }
151
152
153 /*      hash table for vx_info hash */
154
155 #define VX_HASH_SIZE    13
156
157 struct hlist_head vx_info_hash[VX_HASH_SIZE];
158
159 static spinlock_t vx_info_hash_lock = SPIN_LOCK_UNLOCKED;
160
161
162 static inline unsigned int __hashval(xid_t xid)
163 {
164         return (xid % VX_HASH_SIZE);
165 }
166
167
168
169 /*      __hash_vx_info()
170
171         * add the vxi to the global hash table
172         * requires the hash_lock to be held                     */
173
174 static inline void __hash_vx_info(struct vx_info *vxi)
175 {
176         struct hlist_head *head;
177
178         vxd_assert_lock(&vx_info_hash_lock);
179         vxdprintk(VXD_CBIT(xid, 4),
180                 "__hash_vx_info: %p[#%d]", vxi, vxi->vx_id);
181         vxh_hash_vx_info(vxi);
182
183         /* context must not be hashed */
184         BUG_ON(vx_info_state(vxi, VXS_HASHED));
185
186         vxi->vx_state |= VXS_HASHED;
187         head = &vx_info_hash[__hashval(vxi->vx_id)];
188         hlist_add_head(&vxi->vx_hlist, head);
189 }
190
191 /*      __unhash_vx_info()
192
193         * remove the vxi from the global hash table
194         * requires the hash_lock to be held                     */
195
196 static inline void __unhash_vx_info(struct vx_info *vxi)
197 {
198         vxd_assert_lock(&vx_info_hash_lock);
199         vxdprintk(VXD_CBIT(xid, 4),
200                 "__unhash_vx_info: %p[#%d]", vxi, vxi->vx_id);
201         vxh_unhash_vx_info(vxi);
202
203         /* context must be hashed */
204         BUG_ON(!vx_info_state(vxi, VXS_HASHED));
205
206         vxi->vx_state &= ~VXS_HASHED;
207         hlist_del(&vxi->vx_hlist);
208 }
209
210
211 /*      __lookup_vx_info()
212
213         * requires the hash_lock to be held
214         * doesn't increment the vx_refcnt                       */
215
216 static inline struct vx_info *__lookup_vx_info(xid_t xid)
217 {
218         struct hlist_head *head = &vx_info_hash[__hashval(xid)];
219         struct hlist_node *pos;
220         struct vx_info *vxi;
221
222         vxd_assert_lock(&vx_info_hash_lock);
223         hlist_for_each(pos, head) {
224                 vxi = hlist_entry(pos, struct vx_info, vx_hlist);
225
226                 if (vxi->vx_id == xid)
227                         goto found;
228         }
229         vxi = NULL;
230 found:
231         vxdprintk(VXD_CBIT(xid, 0),
232                 "__lookup_vx_info(#%u): %p[#%u]",
233                 xid, vxi, vxi?vxi->vx_id:0);
234         vxh_lookup_vx_info(vxi, xid);
235         return vxi;
236 }
237
238
239 /*      __vx_dynamic_id()
240
241         * find unused dynamic xid
242         * requires the hash_lock to be held                     */
243
244 static inline xid_t __vx_dynamic_id(void)
245 {
246         static xid_t seq = MAX_S_CONTEXT;
247         xid_t barrier = seq;
248
249         vxd_assert_lock(&vx_info_hash_lock);
250         do {
251                 if (++seq > MAX_S_CONTEXT)
252                         seq = MIN_D_CONTEXT;
253                 if (!__lookup_vx_info(seq)) {
254                         vxdprintk(VXD_CBIT(xid, 4),
255                                 "__vx_dynamic_id: [#%d]", seq);
256                         return seq;
257                 }
258         } while (barrier != seq);
259         return 0;
260 }
261
262 #ifdef  CONFIG_VSERVER_LEGACY
263
264 /*      __loc_vx_info()
265
266         * locate or create the requested context
267         * get() it and if new hash it                           */
268
269 static struct vx_info * __loc_vx_info(int id, int *err)
270 {
271         struct vx_info *new, *vxi = NULL;
272
273         vxdprintk(VXD_CBIT(xid, 1), "loc_vx_info(%d)*", id);
274
275         if (!(new = __alloc_vx_info(id))) {
276                 *err = -ENOMEM;
277                 return NULL;
278         }
279
280         /* required to make dynamic xids unique */
281         spin_lock(&vx_info_hash_lock);
282
283         /* dynamic context requested */
284         if (id == VX_DYNAMIC_ID) {
285                 id = __vx_dynamic_id();
286                 if (!id) {
287                         printk(KERN_ERR "no dynamic context available.\n");
288                         goto out_unlock;
289                 }
290                 new->vx_id = id;
291         }
292         /* existing context requested */
293         else if ((vxi = __lookup_vx_info(id))) {
294                 /* context in setup is not available */
295                 if (vxi->vx_flags & VXF_STATE_SETUP) {
296                         vxdprintk(VXD_CBIT(xid, 0),
297                                 "loc_vx_info(%d) = %p (not available)", id, vxi);
298                         vxi = NULL;
299                         *err = -EBUSY;
300                 } else {
301                         vxdprintk(VXD_CBIT(xid, 0),
302                                 "loc_vx_info(%d) = %p (found)", id, vxi);
303                         get_vx_info(vxi);
304                         *err = 0;
305                 }
306                 goto out_unlock;
307         }
308
309         /* new context requested */
310         vxdprintk(VXD_CBIT(xid, 0),
311                 "loc_vx_info(%d) = %p (new)", id, new);
312         __hash_vx_info(get_vx_info(new));
313         vxi = new, new = NULL;
314         *err = 1;
315
316 out_unlock:
317         spin_unlock(&vx_info_hash_lock);
318         vxh_loc_vx_info(vxi, id);
319         if (new)
320                 __dealloc_vx_info(new);
321         return vxi;
322 }
323
324 #endif
325
326 /*      __create_vx_info()
327
328         * create the requested context
329         * get() and hash it                                     */
330
331 static struct vx_info * __create_vx_info(int id)
332 {
333         struct vx_info *new, *vxi = NULL;
334
335         vxdprintk(VXD_CBIT(xid, 1), "create_vx_info(%d)*", id);
336
337         if (!(new = __alloc_vx_info(id)))
338                 return ERR_PTR(-ENOMEM);
339
340         /* required to make dynamic xids unique */
341         spin_lock(&vx_info_hash_lock);
342
343         /* dynamic context requested */
344         if (id == VX_DYNAMIC_ID) {
345                 id = __vx_dynamic_id();
346                 if (!id) {
347                         printk(KERN_ERR "no dynamic context available.\n");
348                         vxi = ERR_PTR(-EAGAIN);
349                         goto out_unlock;
350                 }
351                 new->vx_id = id;
352         }
353         /* static context requested */
354         else if ((vxi = __lookup_vx_info(id))) {
355                 vxdprintk(VXD_CBIT(xid, 0),
356                         "create_vx_info(%d) = %p (already there)", id, vxi);
357                 if (vx_info_flags(vxi, VXF_STATE_SETUP, 0))
358                         vxi = ERR_PTR(-EBUSY);
359                 else
360                         vxi = ERR_PTR(-EEXIST);
361                 goto out_unlock;
362         }
363         /* dynamic xid creation blocker */
364         else if (id >= MIN_D_CONTEXT) {
365                 vxdprintk(VXD_CBIT(xid, 0),
366                         "create_vx_info(%d) (dynamic rejected)", id);
367                 vxi = ERR_PTR(-EINVAL);
368                 goto out_unlock;
369         }
370
371         /* new context */
372         vxdprintk(VXD_CBIT(xid, 0),
373                 "create_vx_info(%d) = %p (new)", id, new);
374         __hash_vx_info(get_vx_info(new));
375         vxi = new, new = NULL;
376
377 out_unlock:
378         spin_unlock(&vx_info_hash_lock);
379         vxh_create_vx_info(IS_ERR(vxi)?NULL:vxi, id);
380         if (new)
381                 __dealloc_vx_info(new);
382         return vxi;
383 }
384
385
386 /*      exported stuff                                          */
387
388
389 void unhash_vx_info(struct vx_info *vxi)
390 {
391         __shutdown_vx_info(vxi);
392         spin_lock(&vx_info_hash_lock);
393         __unhash_vx_info(vxi);
394         spin_unlock(&vx_info_hash_lock);
395         __wakeup_vx_info(vxi);
396 }
397
398
399 /*      lookup_vx_info()
400
401         * search for a vx_info and get() it
402         * negative id means current                             */
403
404 struct vx_info *lookup_vx_info(int id)
405 {
406         struct vx_info *vxi = NULL;
407
408         if (id < 0) {
409                 vxi = get_vx_info(current->vx_info);
410         } else if (id > 1) {
411                 spin_lock(&vx_info_hash_lock);
412                 vxi = get_vx_info(__lookup_vx_info(id));
413                 spin_unlock(&vx_info_hash_lock);
414         }
415         return vxi;
416 }
417
418 /*      xid_is_hashed()
419
420         * verify that xid is still hashed                       */
421
422 int xid_is_hashed(xid_t xid)
423 {
424         int hashed;
425
426         spin_lock(&vx_info_hash_lock);
427         hashed = (__lookup_vx_info(xid) != NULL);
428         spin_unlock(&vx_info_hash_lock);
429         return hashed;
430 }
431
432 #ifdef  CONFIG_VSERVER_LEGACY
433
434 struct vx_info *lookup_or_create_vx_info(int id)
435 {
436         int err;
437
438         return __loc_vx_info(id, &err);
439 }
440
441 #endif
442
443 #ifdef  CONFIG_PROC_FS
444
445 int get_xid_list(int index, unsigned int *xids, int size)
446 {
447         int hindex, nr_xids = 0;
448
449         for (hindex = 0; hindex < VX_HASH_SIZE; hindex++) {
450                 struct hlist_head *head = &vx_info_hash[hindex];
451                 struct hlist_node *pos;
452
453                 spin_lock(&vx_info_hash_lock);
454                 hlist_for_each(pos, head) {
455                         struct vx_info *vxi;
456
457                         if (--index > 0)
458                                 continue;
459
460                         vxi = hlist_entry(pos, struct vx_info, vx_hlist);
461                         xids[nr_xids] = vxi->vx_id;
462                         if (++nr_xids >= size) {
463                                 spin_unlock(&vx_info_hash_lock);
464                                 goto out;
465                         }
466                 }
467                 /* keep the lock time short */
468                 spin_unlock(&vx_info_hash_lock);
469         }
470 out:
471         return nr_xids;
472 }
473 #endif
474
475
476 int vx_migrate_user(struct task_struct *p, struct vx_info *vxi)
477 {
478         struct user_struct *new_user, *old_user;
479
480         if (!p || !vxi)
481                 BUG();
482         new_user = alloc_uid(vxi->vx_id, p->uid);
483         if (!new_user)
484                 return -ENOMEM;
485
486         old_user = p->user;
487         if (new_user != old_user) {
488                 atomic_inc(&new_user->processes);
489                 atomic_dec(&old_user->processes);
490                 p->user = new_user;
491         }
492         free_uid(old_user);
493         return 0;
494 }
495
496 void vx_mask_bcaps(struct vx_info *vxi, struct task_struct *p)
497 {
498         p->cap_effective &= vxi->vx_bcaps;
499         p->cap_inheritable &= vxi->vx_bcaps;
500         p->cap_permitted &= vxi->vx_bcaps;
501 }
502
503
504 #include <linux/file.h>
505
506 static int vx_openfd_task(struct task_struct *tsk)
507 {
508         struct files_struct *files = tsk->files;
509         struct fdtable *fdt;
510         const unsigned long *bptr;
511         int count, total;
512
513         /* no rcu_read_lock() because of spin_lock() */
514         spin_lock(&files->file_lock);
515         fdt = files_fdtable(files);
516         bptr = fdt->open_fds->fds_bits;
517         count = fdt->max_fds / (sizeof(unsigned long) * 8);
518         for (total = 0; count > 0; count--) {
519                 if (*bptr)
520                         total += hweight_long(*bptr);
521                 bptr++;
522         }
523         spin_unlock(&files->file_lock);
524         return total;
525 }
526
527 /*
528  *      migrate task to new context
529  *      gets vxi, puts old_vxi on change
530  */
531
532 int vx_migrate_task(struct task_struct *p, struct vx_info *vxi)
533 {
534         struct vx_info *old_vxi;
535         int ret = 0;
536
537         if (!p || !vxi)
538                 BUG();
539
540         old_vxi = task_get_vx_info(p);
541         if (old_vxi == vxi)
542                 goto out;
543
544         vxdprintk(VXD_CBIT(xid, 5),
545                 "vx_migrate_task(%p,%p[#%d.%d])", p, vxi,
546                 vxi->vx_id, atomic_read(&vxi->vx_usecnt));
547
548         if (!(ret = vx_migrate_user(p, vxi))) {
549                 int openfd;
550
551                 task_lock(p);
552                 openfd = vx_openfd_task(p);
553
554                 if (old_vxi) {
555                         atomic_dec(&old_vxi->cvirt.nr_threads);
556                         atomic_dec(&old_vxi->cvirt.nr_running);
557                         atomic_dec(&old_vxi->limit.rcur[RLIMIT_NPROC]);
558                         /* FIXME: what about the struct files here? */
559                         atomic_sub(openfd, &old_vxi->limit.rcur[VLIMIT_OPENFD]);
560                 }
561                 atomic_inc(&vxi->cvirt.nr_threads);
562                 atomic_inc(&vxi->cvirt.nr_running);
563                 atomic_inc(&vxi->limit.rcur[RLIMIT_NPROC]);
564                 /* FIXME: what about the struct files here? */
565                 atomic_add(openfd, &vxi->limit.rcur[VLIMIT_OPENFD]);
566
567                 if (old_vxi) {
568                         release_vx_info(old_vxi, p);
569                         clr_vx_info(&p->vx_info);
570                 }
571                 claim_vx_info(vxi, p);
572                 set_vx_info(&p->vx_info, vxi);
573                 p->xid = vxi->vx_id;
574
575                 vxdprintk(VXD_CBIT(xid, 5),
576                         "moved task %p into vxi:%p[#%d]",
577                         p, vxi, vxi->vx_id);
578
579                 vx_mask_bcaps(vxi, p);
580                 task_unlock(p);
581         }
582 out:
583         put_vx_info(old_vxi);
584         return ret;
585 }
586
587 int vx_set_reaper(struct vx_info *vxi, struct task_struct *p)
588 {
589         struct task_struct *old_reaper;
590
591         if (!vxi)
592                 return -EINVAL;
593
594         vxdprintk(VXD_CBIT(xid, 6),
595                 "vx_set_reaper(%p[#%d],%p[#%d,%d])",
596                 vxi, vxi->vx_id, p, p->xid, p->pid);
597
598         old_reaper = vxi->vx_reaper;
599         if (old_reaper == p)
600                 return 0;
601
602         /* set new child reaper */
603         get_task_struct(p);
604         vxi->vx_reaper = p;
605         put_task_struct(old_reaper);
606         return 0;
607 }
608
609 int vx_set_init(struct vx_info *vxi, struct task_struct *p)
610 {
611         if (!vxi)
612                 return -EINVAL;
613
614         vxdprintk(VXD_CBIT(xid, 6),
615                 "vx_set_init(%p[#%d],%p[#%d,%d,%d])",
616                 vxi, vxi->vx_id, p, p->xid, p->pid, p->tgid);
617
618         vxi->vx_flags &= ~VXF_STATE_INIT;
619         vxi->vx_initpid = p->tgid;
620         return 0;
621 }
622
623 void vx_exit_init(struct vx_info *vxi, struct task_struct *p, int code)
624 {
625         vxdprintk(VXD_CBIT(xid, 6),
626                 "vx_exit_init(%p[#%d],%p[#%d,%d,%d])",
627                 vxi, vxi->vx_id, p, p->xid, p->pid, p->tgid);
628
629         vxi->exit_code = code;
630         vxi->vx_initpid = 0;
631 }
632
633 void vx_set_persistent(struct vx_info *vxi)
634 {
635         vxdprintk(VXD_CBIT(xid, 6),
636                 "vx_set_persistent(%p[#%d])", vxi, vxi->vx_id);
637
638         get_vx_info(vxi);
639         claim_vx_info(vxi, current);
640 }
641
642 void vx_clear_persistent(struct vx_info *vxi)
643 {
644         vxdprintk(VXD_CBIT(xid, 6),
645                 "vx_clear_persistent(%p[#%d])", vxi, vxi->vx_id);
646
647         release_vx_info(vxi, current);
648         put_vx_info(vxi);
649 }
650
651 void vx_update_persistent(struct vx_info *vxi)
652 {
653         if (vx_info_flags(vxi, VXF_PERSISTENT, 0))
654                 vx_set_persistent(vxi);
655         else
656                 vx_clear_persistent(vxi);
657 }
658
659
660 /*      task must be current or locked          */
661
662 void    exit_vx_info(struct task_struct *p, int code)
663 {
664         struct vx_info *vxi = p->vx_info;
665
666         if (vxi) {
667                 atomic_dec(&vxi->cvirt.nr_threads);
668                 vx_nproc_dec(p);
669
670                 vxi->exit_code = code;
671                 release_vx_info(vxi, p);
672         }
673 }
674
675 void    exit_vx_info_early(struct task_struct *p, int code)
676 {
677         struct vx_info *vxi = p->vx_info;
678
679         if (vxi) {
680                 if (vxi->vx_initpid == p->tgid)
681                         vx_exit_init(vxi, p, code);
682                 if (vxi->vx_reaper == p)
683                         vx_set_reaper(vxi, child_reaper);
684         }
685 }
686
687
688 /* vserver syscall commands below here */
689
690 /* taks xid and vx_info functions */
691
692 #include <asm/uaccess.h>
693
694
695 int vc_task_xid(uint32_t id, void __user *data)
696 {
697         xid_t xid;
698
699         if (id) {
700                 struct task_struct *tsk;
701
702                 if (!vx_check(0, VX_ADMIN|VX_WATCH))
703                         return -EPERM;
704
705                 read_lock(&tasklist_lock);
706                 tsk = find_task_by_real_pid(id);
707                 xid = (tsk) ? tsk->xid : -ESRCH;
708                 read_unlock(&tasklist_lock);
709         }
710         else
711                 xid = vx_current_xid();
712         return xid;
713 }
714
715
716 int vc_vx_info(uint32_t id, void __user *data)
717 {
718         struct vx_info *vxi;
719         struct vcmd_vx_info_v0 vc_data;
720
721         if (!vx_check(0, VX_ADMIN))
722                 return -ENOSYS;
723         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
724                 return -EPERM;
725
726         vxi = lookup_vx_info(id);
727         if (!vxi)
728                 return -ESRCH;
729
730         vc_data.xid = vxi->vx_id;
731         vc_data.initpid = vxi->vx_initpid;
732         put_vx_info(vxi);
733
734         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
735                 return -EFAULT;
736         return 0;
737 }
738
739
740 /* context functions */
741
742 int vc_ctx_create(uint32_t xid, void __user *data)
743 {
744         struct vcmd_ctx_create vc_data = { .flagword = VXF_INIT_SET };
745         struct vx_info *new_vxi;
746         int ret;
747
748         if (!capable(CAP_SYS_ADMIN))
749                 return -EPERM;
750         if (data && copy_from_user (&vc_data, data, sizeof(vc_data)))
751                 return -EFAULT;
752
753         if ((xid > MAX_S_CONTEXT) && (xid != VX_DYNAMIC_ID))
754                 return -EINVAL;
755         if (xid < 2)
756                 return -EINVAL;
757
758         new_vxi = __create_vx_info(xid);
759         if (IS_ERR(new_vxi))
760                 return PTR_ERR(new_vxi);
761
762         /* initial flags */
763         new_vxi->vx_flags = vc_data.flagword;
764
765         /* get a reference for persistent contexts */
766         if ((vc_data.flagword & VXF_PERSISTENT))
767                 vx_set_persistent(new_vxi);
768
769         ret = -ENOEXEC;
770         if (vs_state_change(new_vxi, VSC_STARTUP))
771                 goto out_unhash;
772         ret = vx_migrate_task(current, new_vxi);
773         if (!ret) {
774                 /* return context id on success */
775                 ret = new_vxi->vx_id;
776                 goto out;
777         }
778 out_unhash:
779         /* prepare for context disposal */
780         new_vxi->vx_state |= VXS_SHUTDOWN;
781         if ((vc_data.flagword & VXF_PERSISTENT))
782                 vx_clear_persistent(new_vxi);
783         __unhash_vx_info(new_vxi);
784 out:
785         put_vx_info(new_vxi);
786         return ret;
787 }
788
789
790 int vc_ctx_migrate(uint32_t id, void __user *data)
791 {
792         struct vcmd_ctx_migrate vc_data = { .flagword = 0 };
793         struct vx_info *vxi;
794
795         if (!capable(CAP_SYS_ADMIN))
796                 return -EPERM;
797         if (data && copy_from_user (&vc_data, data, sizeof(vc_data)))
798                 return -EFAULT;
799
800         /* dirty hack until Spectator becomes a cap */
801         if (id == 1) {
802                 current->xid = 1;
803                 return 0;
804         }
805
806         vxi = lookup_vx_info(id);
807         if (!vxi)
808                 return -ESRCH;
809         vx_migrate_task(current, vxi);
810         if (vc_data.flagword & VXM_SET_INIT)
811                 vx_set_init(vxi, current);
812         if (vc_data.flagword & VXM_SET_REAPER)
813                 vx_set_reaper(vxi, current);
814         put_vx_info(vxi);
815         return 0;
816 }
817
818
819 int vc_get_cflags(uint32_t id, void __user *data)
820 {
821         struct vx_info *vxi;
822         struct vcmd_ctx_flags_v0 vc_data;
823
824         if (!capable(CAP_SYS_ADMIN))
825                 return -EPERM;
826
827         vxi = lookup_vx_info(id);
828         if (!vxi)
829                 return -ESRCH;
830
831         vc_data.flagword = vxi->vx_flags;
832
833         /* special STATE flag handling */
834         vc_data.mask = vx_mask_flags(~0UL, vxi->vx_flags, VXF_ONE_TIME);
835
836         put_vx_info(vxi);
837
838         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
839                 return -EFAULT;
840         return 0;
841 }
842
843 int vc_set_cflags(uint32_t id, void __user *data)
844 {
845         struct vx_info *vxi;
846         struct vcmd_ctx_flags_v0 vc_data;
847         uint64_t mask, trigger;
848
849         if (!capable(CAP_SYS_ADMIN))
850                 return -EPERM;
851         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
852                 return -EFAULT;
853
854         vxi = lookup_vx_info(id);
855         if (!vxi)
856                 return -ESRCH;
857
858         /* special STATE flag handling */
859         mask = vx_mask_mask(vc_data.mask, vxi->vx_flags, VXF_ONE_TIME);
860         trigger = (mask & vxi->vx_flags) ^ (mask & vc_data.flagword);
861
862         if (vxi == current->vx_info) {
863                 if (trigger & VXF_STATE_SETUP)
864                         vx_mask_bcaps(vxi, current);
865                 if (trigger & VXF_STATE_INIT) {
866                         vx_set_init(vxi, current);
867                         vx_set_reaper(vxi, current);
868                 }
869         }
870
871         vxi->vx_flags = vx_mask_flags(vxi->vx_flags,
872                 vc_data.flagword, mask);
873         if (trigger & VXF_PERSISTENT)
874                 vx_update_persistent(vxi);
875
876         put_vx_info(vxi);
877         return 0;
878 }
879
880 int vc_get_ccaps(uint32_t id, void __user *data)
881 {
882         struct vx_info *vxi;
883         struct vcmd_ctx_caps_v0 vc_data;
884
885         if (!capable(CAP_SYS_ADMIN))
886                 return -EPERM;
887
888         vxi = lookup_vx_info(id);
889         if (!vxi)
890                 return -ESRCH;
891
892         vc_data.bcaps = vxi->vx_bcaps;
893         vc_data.ccaps = vxi->vx_ccaps;
894         vc_data.cmask = ~0UL;
895         put_vx_info(vxi);
896
897         if (copy_to_user (data, &vc_data, sizeof(vc_data)))
898                 return -EFAULT;
899         return 0;
900 }
901
902 int vc_set_ccaps(uint32_t id, void __user *data)
903 {
904         struct vx_info *vxi;
905         struct vcmd_ctx_caps_v0 vc_data;
906
907         if (!capable(CAP_SYS_ADMIN))
908                 return -EPERM;
909         if (copy_from_user (&vc_data, data, sizeof(vc_data)))
910                 return -EFAULT;
911
912         vxi = lookup_vx_info(id);
913         if (!vxi)
914                 return -ESRCH;
915
916         vxi->vx_bcaps &= vc_data.bcaps;
917         vxi->vx_ccaps = vx_mask_flags(vxi->vx_ccaps,
918                 vc_data.ccaps, vc_data.cmask);
919         put_vx_info(vxi);
920         return 0;
921 }
922
923 #include <linux/module.h>
924
925 EXPORT_SYMBOL_GPL(free_vx_info);
926