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