diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/fs/exec.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/exec.c
--- linux-2.6.9-vs1.9.3-w02/fs/exec.c	2005-01-13 12:40:41.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/exec.c	2005-01-13 13:19:35.000000000 +0100
@@ -436,9 +436,9 @@ int setup_arg_pages(struct linux_binprm 
 		mpnt->vm_flags |= mm->def_flags;
 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
 		insert_vm_struct(mm, mpnt);
-		// mm->stack_vm = mm->total_vm = vma_pages(mpnt);
-		vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
-		mm->stack_vm = mm->total_vm;
+	       // mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+	       vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
+	       mm->stack_vm = mm->total_vm;
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/fs/namespace.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/namespace.c
--- linux-2.6.9-vs1.9.3-w02/fs/namespace.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/namespace.c	2005-01-13 14:21:04.000000000 +0100
@@ -347,8 +347,10 @@ int may_umount(struct vfsmount *mnt)
 
 EXPORT_SYMBOL(may_umount);
 
-static inline void __umount_tree(struct vfsmount *mnt, struct list_head *kill)
+static inline void __umount_list(struct list_head *kill)
 {
+	struct vfsmount *mnt;
+
 	while (!list_empty(kill)) {
 		mnt = list_entry(kill->next, struct vfsmount, mnt_list);
 		list_del_init(&mnt->mnt_list);
@@ -375,7 +377,7 @@ void umount_tree(struct vfsmount *mnt)
 		list_del(&p->mnt_list);
 		list_add(&p->mnt_list, &kill);
 	}
-	__umount_tree(mnt, &kill);
+	__umount_list(&kill);
 }
 
 void umount_unused(struct vfsmount *mnt, struct fs_struct *fs)
@@ -389,7 +391,7 @@ void umount_unused(struct vfsmount *mnt,
 		list_del(&p->mnt_list);
 		list_add(&p->mnt_list, &kill);
 	}
-	__umount_tree(mnt, &kill);
+	__umount_list(&kill);
 }
 
 static int do_umount(struct vfsmount *mnt, int flags)
@@ -647,11 +649,12 @@ out_unlock:
 /*
  * do loopback mount.
  */
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, xid_t xid, int flags)
 {
 	struct nameidata old_nd;
 	struct vfsmount *mnt = NULL;
 	int err = mount_is_safe(nd);
+	int recurse = flags & MS_REC;
 	if (err)
 		return err;
 	if (!old_name || !*old_name)
@@ -1022,6 +1025,8 @@ int copy_mount_options(const void __user
 	return 0;
 }
 
+
+
 /*
  * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/fs/nfs/file.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/nfs/file.c
--- linux-2.6.9-vs1.9.3-w02/fs/nfs/file.c	2004-10-23 05:06:17.000000000 +0200
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/nfs/file.c	2005-01-13 13:19:35.000000000 +0100
@@ -49,8 +49,8 @@ struct file_operations nfs_file_operatio
 	.llseek		= remote_llseek,
 	.read		= do_sync_read,
 	.write		= do_sync_write,
-	.aio_read		= nfs_file_read,
-	.aio_write		= nfs_file_write,
+	.aio_read	= nfs_file_read,
+	.aio_write	= nfs_file_write,
 	.mmap		= nfs_file_mmap,
 	.open		= nfs_file_open,
 	.flush		= nfs_file_flush,
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/fs/proc/base.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/proc/base.c
--- linux-2.6.9-vs1.9.3-w02/fs/proc/base.c	2005-01-13 12:40:41.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/fs/proc/base.c	2005-01-13 13:19:35.000000000 +0100
@@ -1251,6 +1251,9 @@ static struct file_operations proc_tgid_
 static struct inode_operations proc_tgid_attr_inode_operations;
 #endif
 
+extern int proc_pid_vx_info(struct task_struct *, char *);
+extern int proc_pid_nx_info(struct task_struct *, char *);
+
 /* SMP-safe */
 static struct dentry *proc_pident_lookup(struct inode *dir, 
 					 struct dentry *dentry,
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/sched.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/sched.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/sched.h	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/sched.h	2005-01-13 13:19:35.000000000 +0100
@@ -794,15 +794,28 @@ static inline int sas_ss_flags(unsigned 
 #ifdef CONFIG_SECURITY
 /* code is in security.c */
 extern int capable(int cap);
+extern int vx_capable(int cap, int ccap);
 #else
 static inline int capable(int cap)
 {
+	if (vx_check_bit(VXC_CAP_MASK, cap) && !vx_mcaps(1L << cap))
+		return 0;
 	if (cap_raised(current->cap_effective, cap)) {
 		current->flags |= PF_SUPERPRIV;
 		return 1;
 	}
 	return 0;
 }
+
+static inline int vx_capable(int cap, int ccap)
+{
+	if (cap_raised(current->cap_effective, cap) &&
+		vx_ccaps(ccap)) {
+		current->flags |= PF_SUPERPRIV;
+		return 1;
+	}
+	return 0;
+}
 #endif
 
 /*
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vs_base.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_base.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vs_base.h	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_base.h	2005-01-13 13:19:35.000000000 +0100
@@ -18,7 +18,7 @@
  * check current context for ADMIN/WATCH and
  * optionally agains supplied argument
  */
-static __inline__ int __vx_check(xid_t cid, xid_t id, unsigned int mode)
+static inline int __vx_check(xid_t cid, xid_t id, unsigned int mode)
 {
 	if (mode & VX_ARG_MASK) {
 		if ((mode & VX_IDENT) &&
@@ -35,7 +35,8 @@ static __inline__ int __vx_check(xid_t c
 			return 1;
 	}
 	return (((mode & VX_ADMIN) && (cid == 0)) ||
-		((mode & VX_WATCH) && (cid == 1)));
+		((mode & VX_WATCH) && (cid == 1)) ||
+		((mode & VX_HOSTID) && (id == 0)));
 }
 
 
@@ -52,6 +53,8 @@ static __inline__ int __vx_check(xid_t c
 
 #define vx_mask_mask(v,f,m)	(((v) & ~(m)) | ((v) & (f) & (m)))
 
+#define vx_check_bit(v,n)	((v) & (1LL << (n)))
+
 
 /* context flags */
 
@@ -79,6 +82,13 @@ static __inline__ int __vx_check(xid_t c
 #define vx_ccaps(c)	vx_info_ccaps(current->vx_info,(c))
 
 
+#define __vx_mcaps(v)	((v) ? (v)->vx_ccaps >> 32UL : ~0 )
+
+#define vx_info_mcaps(v,c)	(__vx_mcaps(v) & (c))
+
+#define vx_mcaps(c)	vx_info_mcaps(current->vx_info,(c))
+
+
 #define vx_current_bcaps() \
 	(((current->vx_info) && !vx_flags(VXF_STATE_SETUP, 0)) ? \
 	current->vx_info->vx_bcaps : cap_bset)
@@ -89,4 +99,6 @@ static __inline__ int __vx_check(xid_t c
 	(current->vx_info->vx_initpid == (n)))
 
 
+#else
+#warning duplicate inclusion
 #endif
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vs_context.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_context.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vs_context.h	2005-01-13 12:40:42.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_context.h	2005-01-13 14:20:52.000000000 +0100
@@ -3,16 +3,9 @@
 
 
 #include <linux/kernel.h>
-#include <linux/rcupdate.h>
-#include <linux/sched.h>
-
-#include "vserver/context.h"
 #include "vserver/debug.h"
 
 
-extern int proc_pid_vx_info(struct task_struct *, char *);
-
-
 #define get_vx_info(i)	__get_vx_info(i,__FILE__,__LINE__)
 
 static inline struct vx_info *__get_vx_info(struct vx_info *vxi,
@@ -20,6 +13,7 @@ static inline struct vx_info *__get_vx_i
 {
 	if (!vxi)
 		return NULL;
+
 	vxlprintk(VXD_CBIT(xid, 2), "get_vx_info(%p[#%d.%d])",
 		vxi, vxi?vxi->vx_id:0, vxi?atomic_read(&vxi->vx_usecnt):0,
 		_file, _line);
@@ -27,15 +21,13 @@ static inline struct vx_info *__get_vx_i
 	return vxi;
 }
 
-
-extern void free_vx_info(struct vx_info *);
-
 #define put_vx_info(i)	__put_vx_info(i,__FILE__,__LINE__)
 
 static inline void __put_vx_info(struct vx_info *vxi, const char *_file, int _line)
 {
 	if (!vxi)
 		return;
+
 	vxlprintk(VXD_CBIT(xid, 2), "put_vx_info(%p[#%d.%d])",
 		vxi, vxi?vxi->vx_id:0, vxi?atomic_read(&vxi->vx_usecnt):0,
 		_file, _line);
@@ -87,7 +79,7 @@ static inline void __clr_vx_info(struct 
 }
 
 
-#define task_get_vx_info(i)	__task_get_vx_info(i,__FILE__,__LINE__)
+#define task_get_vx_info(p)	__task_get_vx_info(p,__FILE__,__LINE__)
 
 static __inline__ struct vx_info *__task_get_vx_info(struct task_struct *p,
 	const char *_file, int _line)
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vs_cvirt.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_cvirt.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vs_cvirt.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_cvirt.h	2005-01-13 13:19:35.000000000 +0100
@@ -70,11 +70,9 @@ static inline void vx_activate_task(stru
 {
 	struct vx_info *vxi;
 
-	// if ((vxi = task_get_vx_info(p))) {
 	if ((vxi = p->vx_info)) {
 		vx_update_load(vxi);
 		atomic_inc(&vxi->cvirt.nr_running);
-		// put_vx_info(vxi);
 	}
 }
 
@@ -82,14 +80,28 @@ static inline void vx_deactivate_task(st
 {
 	struct vx_info *vxi;
 
-	// if ((vxi = task_get_vx_info(p))) {
 	if ((vxi = p->vx_info)) {
 		vx_update_load(vxi);
 		atomic_dec(&vxi->cvirt.nr_running);
-		// put_vx_info(vxi);
 	}
 }
 
+static inline void vx_uninterruptible_inc(struct task_struct *p)
+{
+	struct vx_info *vxi;
+
+	if ((vxi = p->vx_info))
+		atomic_inc(&vxi->cvirt.nr_uninterruptible);
+}
+
+static inline void vx_uninterruptible_dec(struct task_struct *p)
+{
+	struct vx_info *vxi;
+
+	if ((vxi = p->vx_info))
+		atomic_dec(&vxi->cvirt.nr_uninterruptible);
+}
+
 
 #else
 #warning duplicate inclusion
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vs_dlimit.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_dlimit.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vs_dlimit.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_dlimit.h	2005-01-13 13:19:35.000000000 +0100
@@ -108,7 +108,7 @@ static inline int __dl_alloc_inode(struc
 		dli->dl_inodes_used++;
 #if 0
 	else
-		printk("VSW: DLIMIT hit (%p,#%d), inode %d>=%d @ %s:%d\n",
+		vxwprintk("DLIMIT hit (%p,#%d), inode %d>=%d @ %s:%d",
 			sb, xid,
 			dli->dl_inodes_used, dli->dl_inodes_total,
 			file, line);
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vs_network.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_network.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vs_network.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vs_network.h	2005-01-13 14:20:59.000000000 +0100
@@ -23,10 +23,6 @@ static inline struct nx_info *__get_nx_i
 	return nxi;
 }
 
-
-#define free_nx_info(i) \
-	call_rcu(&i->nx_rcu, rcu_free_nx_info);
-
 #define put_nx_info(i)	__put_nx_info(i,__FILE__,__LINE__)
 
 static inline void __put_nx_info(struct nx_info *nxi, const char *_file, int _line)
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vserver/context.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/context.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vserver/context.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/context.h	2005-01-13 14:20:59.000000000 +0100
@@ -57,15 +57,21 @@
 #define VXC_SECURE_REMOUNT	0x00020000
 
 
+/* vshelper sync commands */
+
+#define	VS_CONTEXT_CREATED	1
+#define	VS_CONTEXT_DESTROY	2
+
+
 #ifdef	__KERNEL__
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 
-#include "cvirt_def.h"
 #include "limit_def.h"
 #include "sched_def.h"
+#include "cvirt_def.h"
 
 struct vx_info {
 	struct hlist_node vx_hlist;		/* linked list of contexts */
@@ -109,7 +115,8 @@ struct vx_info {
 
 #define VX_ADMIN	0x0001
 #define VX_WATCH	0x0002
-#define VX_DUMMY	0x0008
+#define VX_HIDE		0x0004
+#define VX_HOSTID	0x0008
 
 #define VX_IDENT	0x0010
 #define VX_EQUIV	0x0020
@@ -126,9 +133,10 @@ struct vx_info {
 
 struct rcu_head;
 
-// extern void rcu_free_vx_info(struct rcu_head *);
 extern void unhash_vx_info(struct vx_info *);
 
+extern void free_vx_info(struct vx_info *);
+
 extern struct vx_info *locate_vx_info(int);
 extern struct vx_info *locate_or_create_vx_info(int);
 
@@ -139,8 +147,7 @@ extern int vx_migrate_task(struct task_s
 
 extern int proc_pid_vx_info(struct task_struct *, char *);
 
-extern void free_vx_info(struct vx_info *);
-
+extern long vs_context_state(unsigned int);
 
 #endif	/* __KERNEL__ */
 #else	/* _VX_CONTEXT_H */
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vserver/debug.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/debug.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vserver/debug.h	2005-01-13 12:40:42.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/debug.h	2005-01-13 14:20:52.000000000 +0100
@@ -10,8 +10,6 @@
 #define VXD_QUAD(v)	VXD_QPOS(v,0), VXD_QPOS(v,1),		\
 			VXD_QPOS(v,2), VXD_QPOS(v,3)
 
-// #define	VXD_HERE	__FILE__, __LINE__
-
 #define __FUNC__	__func__
 
 
@@ -27,11 +25,12 @@ extern unsigned int vx_debug_cvirt;
 
 
 #define VX_LOGLEVEL	"vxD: "
+#define VX_WARNLEVEL	KERN_WARNING "vxW: "
 
 #define vxdprintk(c,f,x...)					\
 	do {							\
 		if (c)						\
-			printk(VX_LOGLEVEL f "\n", x);		\
+			printk(VX_LOGLEVEL f "\n" , ##x);	\
 	} while (0)
 
 #define vxlprintk(c,f,x...)					\
@@ -46,7 +45,19 @@ extern unsigned int vx_debug_cvirt;
 			printk(VX_LOGLEVEL f " %s@%s:%d\n", x); \
 	} while (0)
 
-#else
+
+#define vxwprintk(c,f,x...)					\
+	do {							\
+		if (c)						\
+			printk(VX_WARNLEVEL f "\n" , ##x);	\
+	} while (0)
+
+
+#define vxd_path(d,m)						\
+	({ static char _buffer[PATH_MAX];			\
+	   d_path((d), (m), _buffer, sizeof(_buffer)); })
+
+#else	/* CONFIG_VSERVER_DEBUG */
 
 #define vx_debug_switch 0
 #define vx_debug_xid	0
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vserver/network.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/network.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vserver/network.h	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/network.h	2005-01-13 13:19:35.000000000 +0100
@@ -45,9 +45,10 @@ struct nx_info {
 
 struct rcu_head;
 
-extern void rcu_free_nx_info(struct rcu_head *);
 extern void unhash_nx_info(struct nx_info *);
 
+extern void free_nx_info(struct nx_info *);
+
 extern struct nx_info *locate_nx_info(int);
 extern struct nx_info *locate_or_create_nx_info(int);
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/include/linux/vserver/switch.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/switch.h
--- linux-2.6.9-vs1.9.3-w02/include/linux/vserver/switch.h	2005-01-13 12:40:42.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/include/linux/vserver/switch.h	2005-01-13 13:19:35.000000000 +0100
@@ -39,7 +39,7 @@
   SPECIAL|EVENT  |       |       |       |FLAGS  |       | |       |       |
 	 |     48|     49|     50|     51|     52|     53| |     54|     55|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
-  SPECIAL|       |       |       |       |RLIMIT |SYSCALL| |       |COMPAT |
+  SPECIAL|DEBUG  |       |       |       |RLIMIT |SYSCALL| |       |COMPAT |
 	 |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
 
@@ -69,6 +69,7 @@
 #define VC_CAT_EVENT		48
 
 #define VC_CAT_FLAGS		52
+#define VC_CAT_DEBUG		56
 #define VC_CAT_RLIMIT		60
 
 #define VC_CAT_SYSTEST		61
@@ -76,7 +77,7 @@
 
 /*  interface version */
 
-#define VCI_VERSION		0x00010022
+#define VCI_VERSION		0x00010026
 
 
 /*  query version */
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/sched.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/sched.c
--- linux-2.6.9-vs1.9.3-w02/kernel/sched.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/sched.c	2005-01-13 13:19:35.000000000 +0100
@@ -911,17 +911,18 @@ static void activate_task(task_t *p, run
 static void __deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
 	rq->nr_running--;
-	if (p->state == TASK_UNINTERRUPTIBLE)
+	if (p->state == TASK_UNINTERRUPTIBLE) {
 		rq->nr_uninterruptible++;
+		vx_uninterruptible_dec(p);
+	}
 	dequeue_task(p, p->array);
-
 	p->array = NULL;
 }
 
 static void deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
-	__deactivate_task(p, rq);
 	vx_deactivate_task(p);
+	__deactivate_task(p, rq);
 }
 
 /*
@@ -1261,6 +1262,9 @@ out_activate:
 	 * to be considered on this CPU.)
 	 */
 	activate_task(p, rq, cpu == this_cpu);
+	/* this is to get the accounting behind the load update */
+	if (old_state == TASK_UNINTERRUPTIBLE)
+		vx_uninterruptible_dec(p);
 	if (!sync || cpu != this_cpu) {
 		if (TASK_PREEMPTS_CURR(p, rq))
 			resched_task(rq->curr);
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/context.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/context.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/context.c	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/context.c	2005-01-13 14:20:52.000000000 +0100
@@ -3,7 +3,7 @@
  *
  *  Virtual Server: Context Support
  *
- *  Copyright (C) 2003-2004  Herbert Pötzl
+ *  Copyright (C) 2003-2005  Herbert Pötzl
  *
  *  V0.01  context helper
  *  V0.02  vx_ctx_kill syscall command
@@ -13,17 +13,18 @@
  *  V0.06  task_xid and info commands
  *  V0.07  context flags and caps
  *  V0.08  switch to RCU based hash
+ *  V0.09  revert to non RCU for now
+ *  V0.10  and back to working RCU hash
  *
  */
 
-#define	_VX_INFO_INIT_
-
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/namespace.h>
 
 #include <linux/sched.h>
+#include <linux/times.h>
 #include <linux/vserver/network.h>
 #include <linux/vserver/legacy.h>
 #include <linux/vserver/limit.h>
@@ -34,6 +35,10 @@
 
 #include <asm/errno.h>
 
+#include "cvirt_init.h"
+#include "limit_init.h"
+#include "sched_init.h"
+
 
 /*	__alloc_vx_info()
 
@@ -123,40 +128,47 @@ static inline int __free_vx_info(struct 
 	return usecnt;
 }
 
-#if 0
-
-static void __rcu_free_vx_info(struct rcu_head *head)
+static void __rcu_put_vx_info(struct rcu_head *head)
 {
 	struct vx_info *vxi = container_of(head, struct vx_info, vx_rcu);
 
-	BUG_ON(!head);
 	vxdprintk(VXD_CBIT(xid, 3),
-		"rcu_free_vx_info(%p): uc=%d", vxi,
-		atomic_read(&vxi->vx_usecnt));
-
-	__free_vx_info(vxi);
+		"__rcu_put_vx_info(%p[#%d]): %d,%d",
+		vxi, vxi->vx_id,
+		atomic_read(&vxi->vx_usecnt),
+		atomic_read(&vxi->vx_refcnt));
+	put_vx_info(vxi);
 }
 
-#endif
-
-void free_vx_info(struct vx_info *vxi)
+void __shutdown_vx_info(struct vx_info *vxi)
 {
 	struct namespace *namespace;
 	struct fs_struct *fs;
 
-	/* context shutdown is mandatory */
-	// BUG_ON(vxi->vx_state != VXS_SHUTDOWN);
+	might_sleep();
 
 	namespace = xchg(&vxi->vx_namespace, NULL);
-	fs = xchg(&vxi->vx_fs, NULL);
-
 	if (namespace)
 		put_namespace(namespace);
+
+	fs = xchg(&vxi->vx_fs, NULL);
 	if (fs)
 		put_fs_struct(fs);
+}
+
+/* exported stuff */
+
+void free_vx_info(struct vx_info *vxi)
+{
+	/* context shutdown is mandatory */
+	// BUG_ON(vxi->vx_state != VXS_SHUTDOWN);
+
+	BUG_ON(vxi->vx_state & VXS_HASHED);
+
+	BUG_ON(vxi->vx_namespace);
+	BUG_ON(vxi->vx_fs);
 
 	BUG_ON(__free_vx_info(vxi));
-	// call_rcu(&i->vx_rcu, __rcu_free_vx_info);
 }
 
 
@@ -204,7 +216,8 @@ static inline void __unhash_vx_info(stru
 		"__unhash_vx_info: %p[#%d]", vxi, vxi->vx_id);
 	vxi->vx_state &= ~VXS_HASHED;
 	hlist_del_rcu(&vxi->vx_hlist);
-	put_vx_info(vxi);
+
+	call_rcu(&vxi->vx_rcu, __rcu_put_vx_info);
 }
 
 
@@ -217,22 +230,28 @@ static inline struct vx_info *__lookup_v
 {
 	struct hlist_head *head = &vx_info_hash[__hashval(xid)];
 	struct hlist_node *pos;
+	struct vx_info *vxi;
 
 	hlist_for_each_rcu(pos, head) {
-		struct vx_info *vxi =
-			hlist_entry(pos, struct vx_info, vx_hlist);
+		vxi = hlist_entry(pos, struct vx_info, vx_hlist);
 
 		if ((vxi->vx_id == xid) &&
 			vx_info_state(vxi, VXS_HASHED))
-			return vxi;
+			goto found;
 	}
-	return NULL;
+	vxi = NULL;
+found:
+	vxdprintk(VXD_CBIT(xid, 0),
+		"__lookup_vx_info(#%u): %p[#%u]",
+		xid, vxi, vxi?vxi->vx_id:0);
+	return vxi;
 }
 
 
 /*	__vx_dynamic_id()
 
 	* find unused dynamic xid
+	* requires the rcu_read_lock()
 	* requires the hash_lock to be held			*/
 
 static inline xid_t __vx_dynamic_id(void)
@@ -268,6 +287,9 @@ static struct vx_info * __loc_vx_info(in
 		return NULL;
 	}
 
+	/* FIXME is this required at all ? */
+	rcu_read_lock();
+	/* required to make dynamic xids unique */
 	spin_lock(&vx_info_hash_lock);
 
 	/* dynamic context requested */
@@ -305,6 +327,7 @@ static struct vx_info * __loc_vx_info(in
 
 out_unlock:
 	spin_unlock(&vx_info_hash_lock);
+	rcu_read_unlock();
 	if (new)
 		__dealloc_vx_info(new);
 	return vxi;
@@ -317,6 +340,7 @@ out_unlock:
 
 void unhash_vx_info(struct vx_info *vxi)
 {
+	__shutdown_vx_info(vxi);
 	spin_lock(&vx_info_hash_lock);
 	__unhash_vx_info(vxi);
 	spin_unlock(&vx_info_hash_lock);
@@ -760,8 +784,6 @@ int vc_set_ccaps(uint32_t id, void __use
 
 #include <linux/module.h>
 
-// EXPORT_SYMBOL_GPL(rcu_free_vx_info);
 EXPORT_SYMBOL_GPL(free_vx_info);
-EXPORT_SYMBOL_GPL(vx_info_hash_lock);
 EXPORT_SYMBOL_GPL(unhash_vx_info);
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/cvirt_init.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/cvirt_init.h
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/cvirt_init.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/cvirt_init.h	2005-01-13 14:26:14.000000000 +0100
@@ -9,6 +9,7 @@ static inline void vx_info_init_cvirt(st
 	jiffies_to_timespec(idle_jiffies, &cvirt->bias_idle);
 	atomic_set(&cvirt->nr_threads, 0);
 	atomic_set(&cvirt->nr_running, 0);
+	atomic_set(&cvirt->nr_uninterruptible, 0);
 	atomic_set(&cvirt->nr_onhold, 0);
 
 	down_read(&uts_sem);
@@ -28,12 +29,15 @@ static inline void vx_info_exit_cvirt(st
 #ifdef	CONFIG_VSERVER_DEBUG
 	int value;
 
-	if ((value = atomic_read(&cvirt->nr_threads)))
-		printk("!!! cvirt: %p[nr_threads] = %d on exit.\n",
-			cvirt, value);
-	if ((value = atomic_read(&cvirt->nr_running)))
-		printk("!!! cvirt: %p[nr_running] = %d on exit.\n",
-			cvirt, value);
+	vxwprintk((value = atomic_read(&cvirt->nr_threads)),
+		"!!! cvirt: %p[nr_threads] = %d on exit.",
+		cvirt, value);
+	vxwprintk((value = atomic_read(&cvirt->nr_running)),
+		"!!! cvirt: %p[nr_running] = %d on exit.",
+		cvirt, value);
+	vxwprintk((value = atomic_read(&cvirt->nr_uninterruptible)),
+		"!!! cvirt: %p[nr_uninterruptible] = %d on exit.",
+		cvirt, value);
 #endif
 	return;
 }
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/cvirt_proc.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/cvirt_proc.h
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/cvirt_proc.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/cvirt_proc.h	2005-01-13 14:26:14.000000000 +0100
@@ -37,10 +37,12 @@ static inline int vx_info_proc_cvirt(str
 	length += sprintf(buffer + length,
 		"nr_threads:\t%d\n"
 		"nr_running:\t%d\n"
+		"nr_unintr:\t%d\n"
 		"nr_onhold:\t%d\n"
 		"loadavg:\t%d.%02d %d.%02d %d.%02d\n"
 		,atomic_read(&cvirt->nr_threads)
 		,atomic_read(&cvirt->nr_running)
+		,atomic_read(&cvirt->nr_uninterruptible)
 		,atomic_read(&cvirt->nr_onhold)
 		,LOAD_INT(a), LOAD_FRAC(a)
 		,LOAD_INT(b), LOAD_FRAC(b)
@@ -49,6 +51,18 @@ static inline int vx_info_proc_cvirt(str
 	return length;
 }
 
+
+static inline long vx_sock_count(struct _vx_cacct *cacct, int type, int pos)
+{
+	return atomic_read(&cacct->sock[type][pos].count);
+}
+
+
+static inline long vx_sock_total(struct _vx_cacct *cacct, int type, int pos)
+{
+	return atomic_read(&cacct->sock[type][pos].total);
+}
+
 static inline int vx_info_proc_cacct(struct _vx_cacct *cacct, char *buffer)
 {
 	int i,j, length = 0;
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/helper.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/helper.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/helper.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/helper.c	2005-01-13 13:19:35.000000000 +0100
@@ -89,3 +89,34 @@ long vs_reboot(unsigned int cmd, void * 
 	return 0;
 }
 
+long vs_context_state(unsigned int cmd)
+{
+	char id_buf[8], cmd_buf[32];
+
+	char *argv[] = {vshelper_path, NULL, id_buf, NULL, 0};
+	char *envp[] = {"HOME=/", "TERM=linux",
+			"PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0};
+
+	snprintf(id_buf, sizeof(id_buf)-1, "%d", vx_current_xid());
+	snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
+
+	switch (cmd) {
+	case VS_CONTEXT_CREATED:
+		argv[1] = "startup";
+		break;
+	case VS_CONTEXT_DESTROY:
+		argv[1] = "shutdown";
+		break;
+	default:
+		return 0;
+	}
+
+	if (call_usermodehelper(*argv, argv, envp, 1)) {
+		printk( KERN_WARNING
+			"vs_context_state(): failed to exec (%s %s %s %s)\n",
+			vshelper_path, argv[1], argv[2], argv[3]);
+		return 0;
+	}
+	return 0;
+}
+
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/inode.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/inode.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/inode.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/inode.c	2005-01-13 14:21:04.000000000 +0100
@@ -60,7 +60,7 @@ static int __vc_get_iattr(struct inode *
 int vc_get_iattr(uint32_t id, void __user *data)
 {
 	struct nameidata nd;
-	struct vcmd_ctx_iattr_v1 vc_data;
+	struct vcmd_ctx_iattr_v1 vc_data = { .xid = -1 };
 	int ret;
 
 	if (!vx_check(0, VX_ADMIN))
@@ -83,7 +83,7 @@ int vc_get_iattr(uint32_t id, void __use
 static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask)
 {
 	struct inode *in = de->d_inode;
-	int error = 0, is_proc = 0;
+	int error = 0, is_proc = 0, has_xid = 0;
 
 	if (!in || !in->i_sb)
 		return -ESRCH;
@@ -91,7 +91,10 @@ static int __vc_set_iattr(struct dentry 
 	is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
 	if ((*mask & IATTR_FLAGS) && !is_proc)
 		return -EINVAL;
-	if ((*mask & IATTR_XID) && !(in->i_sb->s_flags & MS_TAGXID))
+
+	has_xid = (in->i_sb->s_flags & MS_TAGXID) ||
+		(in->i_sb->s_magic == DEVPTS_SUPER_MAGIC);
+	if ((*mask & IATTR_XID) && !has_xid)
 		return -EINVAL;
 
 	down(&in->i_sem);
@@ -175,7 +178,6 @@ int vc_set_iattr(uint32_t id, void __use
 
 
 #ifdef	CONFIG_VSERVER_LEGACY
-#include <linux/proc_fs.h>
 
 #define PROC_DYNAMIC_FIRST 0xF0000000UL
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/legacy.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/legacy.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/legacy.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/legacy.c	2005-01-13 13:19:35.000000000 +0100
@@ -59,8 +59,9 @@ int vc_new_s_context(uint32_t ctx, void 
 		return ret;
 	}
 
-	if (!vx_check(0, VX_ADMIN) ||
-		!capable(CAP_SYS_ADMIN) || vx_flags(VX_INFO_PRIVATE, 0))
+	if (!vx_check(0, VX_ADMIN) || !capable(CAP_SYS_ADMIN)
+		/* might make sense in the future, or not ... */
+		|| vx_flags(VX_INFO_LOCK, 0))
 		return -EPERM;
 
 	/* ugly hack for Spectator */
@@ -80,6 +81,12 @@ int vc_new_s_context(uint32_t ctx, void 
 
 	if (!new_vxi)
 		return -EINVAL;
+
+	ret = -EPERM;
+	if (!vx_info_flags(new_vxi, VXF_STATE_SETUP, 0) &&
+		vx_info_flags(new_vxi, VX_INFO_PRIVATE, 0))
+		goto out_put;
+
 	new_vxi->vx_flags &= ~(VXF_STATE_SETUP|VXF_STATE_INIT);
 
 	ret = vx_migrate_task(current, new_vxi);
@@ -97,6 +104,7 @@ int vc_new_s_context(uint32_t ctx, void 
 				current->rlim[RLIMIT_NPROC].rlim_max;
 		ret = new_vxi->vx_id;
 	}
+out_put:
 	put_vx_info(new_vxi);
 	return ret;
 }
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/limit_init.h linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/limit_init.h
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/limit_init.h	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/limit_init.h	2005-01-13 13:19:35.000000000 +0100
@@ -19,9 +19,9 @@ static inline void vx_info_exit_limit(st
 
 	for (lim=0; lim<NUM_LIMITS; lim++) {
 		value = atomic_read(&limit->rcur[lim]);
-		if (value)
-			printk("!!! limit: %p[%s,%d] = %ld on exit.\n",
-				limit, vlimit_name[lim], lim, value);
+		vxwprintk(value,
+			"!!! limit: %p[%s,%d] = %ld on exit.",
+			limit, vlimit_name[lim], lim, value);
 	}
 #endif
 }
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/network.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/network.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/network.c	2005-01-13 13:18:53.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/network.c	2005-01-13 13:19:35.000000000 +0100
@@ -69,6 +69,35 @@ static void __dealloc_nx_info(struct nx_
 	kfree(nxi);
 }
 
+static inline int __free_nx_info(struct nx_info *nxi)
+{
+	int usecnt, refcnt;
+
+	BUG_ON(!nxi);
+
+	usecnt = atomic_read(&nxi->nx_usecnt);
+	BUG_ON(usecnt < 0);
+
+	refcnt = atomic_read(&nxi->nx_refcnt);
+	BUG_ON(refcnt < 0);
+
+	if (!usecnt)
+		__dealloc_nx_info(nxi);
+	return usecnt;
+}
+
+static void __rcu_put_nx_info(struct rcu_head *head)
+{
+	struct nx_info *nxi = container_of(head, struct nx_info, nx_rcu);
+
+	vxdprintk(VXD_CBIT(nid, 3),
+		"__rcu_put_nx_info(%p[#%d]): %d,%d",
+		nxi, nxi->nx_id,
+		atomic_read(&nxi->nx_usecnt),
+		atomic_read(&nxi->nx_refcnt));
+	put_nx_info(nxi);
+}
+
 
 /*	hash table for nx_info hash */
 
@@ -112,7 +141,7 @@ static inline void __unhash_nx_info(stru
 	vxdprintk(VXD_CBIT(nid, 4),
 		"__unhash_nx_info: %p[#%d]", nxi, nxi->nx_id);
 	hlist_del_rcu(&nxi->nx_hlist);
-	put_nx_info(nxi);
+	call_rcu(&nxi->nx_rcu, __rcu_put_nx_info);
 }
 
 
@@ -141,6 +170,7 @@ static inline struct nx_info *__lookup_n
 /*	__nx_dynamic_id()
 
 	* find unused dynamic nid
+	* requires the rcu_read_lock()
 	* requires the hash_lock to be held			*/
 
 static inline nid_t __nx_dynamic_id(void)
@@ -176,6 +206,9 @@ static struct nx_info * __loc_nx_info(in
 		return NULL;
 	}
 
+	/* FIXME is this required at all ? */
+	rcu_read_lock();
+	/* required to make dynamic xids unique */
 	spin_lock(&nx_info_hash_lock);
 
 	/* dynamic context requested */
@@ -213,6 +246,7 @@ static struct nx_info * __loc_nx_info(in
 
 out_unlock:
 	spin_unlock(&nx_info_hash_lock);
+	rcu_read_unlock();
 	if (new)
 		__dealloc_nx_info(new);
 	return nxi;
@@ -222,28 +256,9 @@ out_unlock:
 
 /*	exported stuff						*/
 
-
-
-
-void rcu_free_nx_info(struct rcu_head *head)
+void free_nx_info(struct nx_info *nxi)
 {
-	struct nx_info *nxi = container_of(head, struct nx_info, nx_rcu);
-	int usecnt, refcnt;
-
-	BUG_ON(!nxi || !head);
-
-	usecnt = atomic_read(&nxi->nx_usecnt);
-	BUG_ON(usecnt < 0);
-
-	refcnt = atomic_read(&nxi->nx_refcnt);
-	BUG_ON(refcnt < 0);
-
-	vxdprintk(VXD_CBIT(nid, 3),
-		"rcu_free_nx_info(%p): uc=%d", nxi, usecnt);
-	if (!usecnt)
-		__dealloc_nx_info(nxi);
-	else
-		printk("!!! rcu didn't free\n");
+	BUG_ON(__free_nx_info(nxi));
 }
 
 void unhash_nx_info(struct nx_info *nxi)
@@ -695,7 +710,6 @@ int vc_set_ncaps(uint32_t id, void __use
 
 #include <linux/module.h>
 
-EXPORT_SYMBOL_GPL(rcu_free_nx_info);
-EXPORT_SYMBOL_GPL(nx_info_hash_lock);
+EXPORT_SYMBOL_GPL(free_nx_info);
 EXPORT_SYMBOL_GPL(unhash_nx_info);
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/switch.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/switch.c
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/switch.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/kernel/vserver/switch.c	2005-01-13 14:20:52.000000000 +0100
@@ -3,12 +3,13 @@
  *
  *  Virtual Server: Syscall Switch
  *
- *  Copyright (C) 2003-2004  Herbert Pötzl
+ *  Copyright (C) 2003-2005  Herbert Pötzl
  *
  *  V0.01  syscall switch
  *  V0.02  added signal to context
  *  V0.03  added rlimit functions
  *  V0.04  added iattr, task/xid functions
+ *  V0.05  added debug/history stuff
  *
  */
 
@@ -45,14 +46,21 @@ vc_get_version(uint32_t id)
 extern asmlinkage long
 sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 {
-	if (!capable(CAP_CONTEXT))
-		return -EPERM;
-
 	vxdprintk(VXD_CBIT(switch, 0),
 		"vc: VCMD_%02d_%d[%d], %d",
 		VC_CATEGORY(cmd), VC_COMMAND(cmd),
 		VC_VERSION(cmd), id);
 
+#ifdef	CONFIG_VSERVER_LEGACY
+	if (!capable(CAP_CONTEXT) &&
+		/* dirty hack for capremove */
+		!(cmd==VCMD_new_s_context && id==-2))
+		return -EPERM;
+#else
+	if (!capable(CAP_CONTEXT))
+		return -EPERM;
+#endif
+
 	switch (cmd) {
 	case VCMD_get_version:
 		return vc_get_version(id);
@@ -154,9 +162,11 @@ sys_vserver(uint32_t cmd, uint32_t id, v
 	case VCMD_wait_exit:
 		return vc_wait_exit(id, data);
 
-#ifdef	CONFIG_VSERVER_LEGACY
 	case VCMD_create_context:
+#ifdef	CONFIG_VSERVER_LEGACY
 		return vc_ctx_create(id, data);
+#else
+		return -ENOSYS;
 #endif
 
 	case VCMD_get_iattr:
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/security/security.c linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/security/security.c
--- linux-2.6.9-vs1.9.3-w02/security/security.c	2004-10-23 05:06:28.000000000 +0200
+++ linux-2.6.9-vs1.9.3-w03-h3-p2-x1-t1/security/security.c	2005-01-13 13:19:35.000000000 +0100
@@ -191,6 +191,8 @@ int mod_unreg_security (const char *name
  */
 int capable (int cap)
 {
+	if (vx_check_bit(VXC_CAP_MASK, cap) && !vx_mcaps(1L << cap))
+		return 0;
 	if (security_ops->capable (current, cap)) {
 		/* capability denied */
 		return 0;
@@ -201,9 +203,24 @@ int capable (int cap)
 	return 1;
 }
 
+int vx_capable(int cap, int ccap)
+{
+	if (security_ops->capable(current, cap)) {
+		/* capability denied */
+		return 0;
+	}
+	if (!vx_ccaps(ccap))
+		return 0;
+
+	/* capability granted */
+	current->flags |= PF_SUPERPRIV;
+	return 1;
+}
+
 EXPORT_SYMBOL_GPL(register_security);
 EXPORT_SYMBOL_GPL(unregister_security);
 EXPORT_SYMBOL_GPL(mod_reg_security);
 EXPORT_SYMBOL_GPL(mod_unreg_security);
 EXPORT_SYMBOL(capable);
+EXPORT_SYMBOL(vx_capable);
 EXPORT_SYMBOL(security_ops);
