--- linux-2.4.24-ck1-vs1.3.4/Makefile	Tue Jan  6 07:06:56 2004
+++ linux-2.4.24-ck1-vs1.3.5/Makefile	Wed Jan 14 02:06:03 2004
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 24
-EXTRAVERSION = -ck1-vs1.3.4
+EXTRAVERSION = -ck1-vs1.3.5
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
--- linux-2.4.24-ck1-vs1.3.4/fs/ioctl.c	Mon Aug 25 13:44:43 2003
+++ linux-2.4.24-ck1-vs1.3.5/fs/ioctl.c	Wed Jan 14 02:06:03 2004
@@ -7,10 +7,15 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
+#include <linux/proc_fs.h>
+#include <linux/vcontext.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+extern int vx_proc_ioctl(struct inode *, struct file *,
+	unsigned int, unsigned long);
+
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
 	int error;
@@ -110,6 +115,12 @@ asmlinkage long sys_ioctl(unsigned int f
 			}
 			else
 				error = -ENOTTY;
+			break;
+		case FIOC_GETXFLG:
+		case FIOC_SETXFLG:
+			error = -ENOTTY;
+			if (filp->f_dentry->d_inode->i_sb->s_magic == PROC_SUPER_MAGIC)
+				error = vx_proc_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
 			break;
 		default:
 			error = -ENOTTY;
--- linux-2.4.24-ck1-vs1.3.4/fs/proc/base.c	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/fs/proc/base.c	Wed Jan 14 02:06:03 2004
@@ -1080,12 +1080,10 @@ struct dentry *proc_pid_lookup(struct in
 	if (!task)
 		goto out;
 
-	if (pid != 1 && !vx_check(task->vx_id, VX_WATCH|VX_IDENT)) {
-		free_task_struct(task);
-		goto out;
-	}
-	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO);
-
+	inode = NULL;
+	if (pid == 1 || vx_check(task->vx_id, VX_WATCH|VX_IDENT))
+		inode = proc_pid_make_inode(dir->i_sb,
+			task, PROC_PID_INO);
 	free_task_struct(task);
 
 	if (!inode)
@@ -1112,7 +1110,7 @@ void proc_pid_delete_inode(struct inode 
 }
 
 #define PROC_NUMBUF 10
-#define PROC_MAXPIDS 20
+#define PROC_MAXPIDS 32
 
 /*
  * Get a few pid's to return for filldir - we need to hold the
--- linux-2.4.24-ck1-vs1.3.4/fs/proc/generic.c	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/fs/proc/generic.c	Wed Jan 14 02:06:03 2004
@@ -270,6 +268,8 @@ struct dentry *proc_lookup(struct inode 
 				continue;
 			if (de->namelen != dentry->d_name.len)
 				continue;
+			if (!vx_weak_check(0, de->vx_flags))
+				continue;
 			if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
 				int ino = de->low_ino;
 				error = -EINVAL;
@@ -337,7 +337,7 @@ int proc_readdir(struct file * filp,
 			}
 
 			do {
-				if (de->vx_flags && !vx_check(de->xid, de->vx_flags))
+				if (!vx_weak_check(0, de->vx_flags))
 					goto skip;
 				if (filldir(dirent, de->name, de->namelen, filp->f_pos,
 					    de->low_ino, de->mode >> 12) < 0)
@@ -449,6 +449,7 @@ static struct proc_dir_entry *proc_creat
 	ent->namelen = len;
 	ent->mode = mode;
 	ent->nlink = nlink;
+	ent->vx_flags = VX_ADMIN;
  out:
 	return ent;
 }
@@ -469,7 +470,8 @@ struct proc_dir_entry *proc_symlink(cons
 				kfree(ent->data);
 				kfree(ent);
 				ent = NULL;
-			}
+			} else
+				ent->vx_flags = 0;
 		} else {
 			kfree(ent);
 			ent = NULL;
--- linux-2.4.24-ck1-vs1.3.4/fs/proc/inode.c	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/fs/proc/inode.c	Wed Jan 14 02:06:04 2004
@@ -154,7 +154,6 @@ printk("proc_iget: using deleted entry %
 			inode->i_uid = de->uid;
 			inode->i_gid = de->gid;
 		}
-		inode->i_xid = de->xid;
 		if (de->vx_flags)
 			inode->u.proc_i.vx_flags = de->vx_flags;
 		if (de->size)
--- linux-2.4.24-ck1-vs1.3.4/fs/proc/root.c	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/fs/proc/root.c	Wed Jan 14 02:06:04 2004
@@ -25,6 +25,8 @@ struct proc_dir_entry *proc_sys_root;
 #endif
 struct proc_dir_entry *proc_virtual;
 
+extern void proc_vx_init(void);
+
 
 static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE);
 
@@ -71,7 +73,7 @@ void __init proc_root_init(void)
 	proc_rtas_init();
 #endif
 	proc_bus = proc_mkdir("bus", 0);
-	proc_virtual = proc_mkdir("virtual", 0);
+	proc_vx_init();
 }
 
 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
@@ -148,5 +150,4 @@ EXPORT_SYMBOL(proc_root);
 EXPORT_SYMBOL(proc_root_fs);
 EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_bus);
-EXPORT_SYMBOL(proc_virtual);
 EXPORT_SYMBOL(proc_root_driver);
--- linux-2.4.24-ck1-vs1.3.4/fs/proc/virtual.c	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/fs/proc/virtual.c	Wed Jan 14 02:06:04 2004
@@ -9,6 +9,7 @@
  *  V0.02  adaptation vs1.3.0
  *  V0.03  proc permissions
  *  V0.04  locking/generic
+ *  V0.05  next generation procfs
  *
  */
 
@@ -22,97 +23,54 @@
 #include <linux/vinline.h>
 
 
-extern struct proc_dir_entry *proc_virtual;
+static struct proc_dir_entry *proc_virtual;
 
-static struct proc_dir_entry *proc_virtual_info;
+enum xid_directory_inos {
+	PROC_XID_INO = 32,
+	PROC_XID_INFO,
+	PROC_XID_STATUS,
+	PROC_XID_LIMIT,
+};
 
 
-char *task_vinfo(struct task_struct *p, char *buffer)
-{
-	return buffer + sprintf(buffer,
-		"VxID:\t%d\n"
-		,p->vx_id);
-}
 
-int proc_pid_vinfo(struct task_struct *p, char *buffer)
-{
-	char * orig = buffer;
+/* first the actual feeds */
 
-        buffer = task_vinfo(p, buffer);
-        return buffer - orig;
-}
 
-static int __generic_info_read_func(char *page, char **start,
-	off_t off, int count, int *eof, void *data,
-	char *(*info_func)(void *, char *))
+static int proc_virtual_info(struct vx_info *vxi, char *buffer)
 {
-	int len;
-	char *buffer = page;
-
-	buffer = info_func(data, buffer);
-
-	len = buffer-page;
-	if (len <= off+count) *eof = 1;
-	
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
+	return sprintf(buffer,
+		"VCIVersion:\t%04x:%04x\n"
+		,VCI_VERSION >> 16
+		,VCI_VERSION & 0xFFFF);
 }
 
 
-char *vx_proc_info (void *data, char *buffer)
+int proc_xid_info (struct vx_info *vxi, char *buffer)
 {
-	struct vx_info *vxi = find_vx_info((int)data);
-	if (vxi)
-		buffer += sprintf(buffer,
+	return sprintf(buffer,
 		"ID:\t%d\n"
 		"Info:\t%p\n"
 		"Init:\t%d\n"
 		,vxi->vx_id
 		,vxi
 		,vxi->vx_initpid);
-	put_vx_info(vxi);
-	return buffer;
 }
 
-int vx_info_read_func (char *page, char **start,
-	off_t off, int count, int *eof, void *data)
-{
-	return __generic_info_read_func(page, start,
-	    off, count, eof, data, vx_proc_info);
-}
-
-
-char *vx_proc_status (void *data, char *buffer)
+int proc_xid_status (struct vx_info *vxi, char *buffer)
 {
-	struct vx_info *vxi = find_vx_info((int)data);
-	if (vxi)
-		buffer += sprintf(buffer,
+	return sprintf(buffer,
 		"RefC:\t%d\n"		
 		"Flags:\t%08x\n"
 		"Ticks:\t%d\n"		
 		,atomic_read(&vxi->vx_refcount)
 		,vxi->vx_flags
 		,atomic_read(&vxi->limit.ticks));
-	put_vx_info(vxi);
-	return buffer;
-}
-
-int vx_status_read_func (char *page, char **start,
-	off_t off, int count, int *eof, void *data)
-{
-	return __generic_info_read_func(page, start,
-	    off, count, eof, data, vx_proc_status);
 }
 
-
-char *vx_proc_limit (void *data, char *buffer)
+int proc_xid_limit (struct vx_info *vxi, char *buffer)
 {
-	struct vx_info *vxi = find_vx_info((int)data);
-	if (vxi)
-		buffer += sprintf(buffer,
+	return sprintf(buffer,
 		"VM:\t%8d/%ld\n"
 		"VML:\t%8d/%ld\n"		
 		"RSS:\t%8d/%ld\n"
@@ -122,112 +80,434 @@ char *vx_proc_limit (void *data, char *b
 		,vxi->limit.rlim[RLIMIT_MEMLOCK]
 		,atomic_read(&vxi->limit.res[RLIMIT_RSS])
 		,vxi->limit.rlim[RLIMIT_RSS]);
-	put_vx_info(vxi);
-	return buffer;
 }
 
-int vx_limit_read_func (char *page, char **start,
-	off_t off, int count, int *eof, void *data)
+
+
+
+/* here the inode helpers */
+
+
+
+#define fake_ino(xid,ino) (((xid)<<16)|(ino))
+
+#define MAX_MULBY10	((~0U-9)/10)
+
+
+static struct inode *proc_xid_make_inode(struct super_block * sb,
+	struct vx_info *vxi, int ino)
 {
-	return __generic_info_read_func(page, start,
-	    off, count, eof, data, vx_proc_limit);
+	struct inode *inode = new_inode(sb);
+	xid_t xid = (vxi)?vxi->vx_id:1;
+
+	if (!inode)
+		goto out;
+
+	inode->i_mtime = inode->i_atime =
+		inode->i_ctime = CURRENT_TIME;
+	inode->i_ino = fake_ino(xid, ino);
+
+	inode->u.generic_ip = vxi; /* reference from above */
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_xid = xid;
+out:
+	return inode;
 }
 
+void proc_xid_delete_inode(struct inode *inode)
+{
+	struct vx_info *vxi = (struct vx_info *)inode->u.generic_ip;
 
-static int vx_proc_permission(struct inode *inode, int mask)
+	if (vxi)
+		put_vx_info(vxi);
+}
+
+
+#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
+
+static ssize_t proc_xid_info_read(struct file * file, char * buf,
+			  size_t count, loff_t *ppos)
 {
-	vxdprintk("vx_proc_permission(%p) = #%d,%04x\n",
-		inode, inode->i_xid, inode->u.proc_i.vx_flags);
-	if (vx_check(inode->i_xid, inode->u.proc_i.vx_flags))
+	struct inode * inode = file->f_dentry->d_inode;
+	unsigned long page;
+	ssize_t length;
+	ssize_t end;
+	struct vx_info *vxi =
+		(struct vx_info *)inode->u.generic_ip;
+
+	if (count > PROC_BLOCK_SIZE)
+		count = PROC_BLOCK_SIZE;
+	if (!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	length = inode->u.proc_i.op.proc_xid_read(vxi, (char*)page);
+
+	if (length < 0) {
+		free_page(page);
+		return length;
+	}
+	/* Static 4kB (or whatever) block capacity */
+	if (*ppos >= length) {
+		free_page(page);
 		return 0;
-	vxdprintk("vx_proc_permission(%p) #%d != #%d\n",
-		inode, inode->i_xid, vx_current_id());
-	return -ENOENT;
+	}
+	if (count + *ppos > length)
+		count = length - *ppos;
+	end = count + *ppos;
+	copy_to_user(buf, (char *) page + *ppos, count);
+	*ppos = end;
+	free_page(page);
+	return count;
 }
 
-static struct inode_operations vx_proc_inode_operations = {
-	lookup:		proc_lookup,
-	permission:	vx_proc_permission,
+static struct file_operations proc_xid_info_file_operations = {
+	read:		proc_xid_info_read,
 };
 
 
-int vx_proc_create(struct vx_info *vxi)
+
+
+/* here comes the lower level (xid) */
+
+
+struct xid_entry {
+	int type;
+	int len;
+	char *name;
+	mode_t mode;
+};
+
+#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
+
+static struct xid_entry base_stuff[] = {
+	E(PROC_XID_INFO,	"info",		S_IFREG|S_IRUGO),
+	E(PROC_XID_STATUS,	"status",	S_IFREG|S_IRUGO),
+	E(PROC_XID_LIMIT,	"limit",	S_IFREG|S_IRUGO),
+	{0,0,NULL,0}
+};
+
+static struct dentry *proc_xid_lookup(struct inode *dir,
+	struct dentry *dentry)
 {
-	struct proc_dir_entry *entry, *sub;
-	char name[8];
+	struct inode *inode;
+	struct vx_info *vxi = (struct vx_info *)dir->u.generic_ip;
+	struct xid_entry *p;
+	int error;
 
-	snprintf(name, sizeof(name)-1, "%d", vxi->vx_id);
-	entry = create_proc_entry(name,
-		S_IFDIR|S_IXUGO, proc_virtual);
-	if (!entry)
-		goto no_entry;
-	entry->vx_flags = VX_ADMIN|VX_WATCH|VX_IDENT;
-	entry->xid = vxi->vx_id;
-	entry->proc_iops = &vx_proc_inode_operations;
-	vxi->vx_procent = entry;
-	sub = create_proc_read_entry("info",
-		S_IFREG|S_IRUGO|S_IWUSR,
-		entry, vx_info_read_func, (void *)vxi->vx_id);
-	if (!sub)
-		goto no_info;
-	sub = create_proc_read_entry("status",
-		S_IFREG|S_IRUGO|S_IWUSR,
-		entry, vx_status_read_func, (void *)vxi->vx_id);
-	if (!sub)
-		goto no_status;
-	sub = create_proc_read_entry("limit",
-		S_IFREG|S_IRUGO|S_IWUSR,
-		entry, vx_limit_read_func, (void *)vxi->vx_id);
-	if (!sub)
-		goto no_limit;
-	return 0;
-no_limit:
-	remove_proc_entry("status", entry);
-no_status:
-	remove_proc_entry("info", entry);
-no_info:
-	remove_proc_entry(name, proc_virtual);
-no_entry:
-	return -ENOMEM;
+	error = -ENOENT;
+	inode = NULL;
+
+	for (p = base_stuff; p->name; p++) {
+		if (p->len != dentry->d_name.len)
+			continue;
+		if (!memcmp(dentry->d_name.name, p->name, p->len))
+			break;
+	}
+	if (!p->name)
+		goto out;
+
+	error = -EINVAL;
+	inode = proc_xid_make_inode(dir->i_sb, vxi, p->type);
+	if (!inode)
+		goto out;
+
+	switch(p->type) {
+		case PROC_XID_INFO:
+			inode->u.proc_i.op.proc_xid_read = proc_xid_info;
+			break;
+		case PROC_XID_STATUS:
+			inode->u.proc_i.op.proc_xid_read = proc_xid_status;
+			break;
+		case PROC_XID_LIMIT:
+			inode->u.proc_i.op.proc_xid_read = proc_xid_limit;
+			break;
+		default:
+			printk("procfs: impossible type (%d)",p->type);
+			iput(inode);
+			return ERR_PTR(-EINVAL);
+	}
+	inode->i_mode = p->mode;
+	inode->i_fop = &proc_xid_info_file_operations;
+	inode->i_nlink = 1;
+	inode->i_flags|=S_IMMUTABLE;
+	
+//	dentry->d_op = &pid_dentry_operations;
+	d_add(dentry, inode);
+	return NULL;
+
+out:
+	return ERR_PTR(error);
 }
 
-int vx_proc_destroy(struct vx_info *vxi)
+
+static int proc_xid_readdir(struct file * filp,
+	void * dirent, filldir_t filldir)
 {
-	struct proc_dir_entry *entry = vxi->vx_procent;
-	if (!entry)
-		return 0;
-	vxi->vx_procent = NULL;
-	remove_proc_entry("limit", entry);
-	remove_proc_entry("status", entry);
-	remove_proc_entry("info", entry);
-	remove_proc_entry(entry->name, proc_virtual);
-	return 0;
+	int i, xid;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct vx_info *vxi = (struct vx_info *)inode->u.generic_ip;
+	struct xid_entry *p;
+	
+	xid = vxi->vx_id;
+	i = filp->f_pos;
+	switch (i) {
+		case 0:
+			if (filldir(dirent, ".", 1, i,
+				inode->i_ino, DT_DIR) < 0)
+				return 0;
+			i++;
+			filp->f_pos++;
+			/* fall through */
+		case 1:
+			if (filldir(dirent, "..", 2, i,
+				PROC_ROOT_INO, DT_DIR) < 0)
+				return 0;
+			i++;
+			filp->f_pos++;
+			/* fall through */
+		default:
+			i -= 2;
+			if (i>=sizeof(base_stuff)/sizeof(base_stuff[0]))
+				return 1;
+			p = base_stuff + i;
+			while (p->name) {
+				if (filldir(dirent, p->name, p->len,
+					filp->f_pos, fake_ino(xid, p->type),
+					p->mode >> 12) < 0)
+					return 0;
+				filp->f_pos++;
+				p++;
+			}
+	}
+	return 1;
 }
 
+static struct file_operations proc_xid_operations = {
+	read:		generic_read_dir,
+	readdir:	proc_xid_readdir,
+};
 
-char *vs_proc_info(void *data, char *buffer)
+static struct inode_operations proc_xid_inode_operations = {
+	lookup:		proc_xid_lookup,
+};
+
+
+
+
+
+/* now the upper level (virtual) */
+
+struct dentry *proc_virtual_lookup(struct inode *dir, struct dentry * dentry)
 {
-	buffer += sprintf(buffer,
-		"VCIVersion:\t%04x:%04x\n"
-		,VCI_VERSION >> 16
-		,VCI_VERSION & 0xFFFF);
-	return buffer;
+	int xid, c;
+	struct vx_info *vxi;
+	const char *name;
+	struct inode *inode;
+	int len;
+
+	xid = 0;
+	name = dentry->d_name.name;
+	len = dentry->d_name.len;
+	if (len == 7 && !memcmp(name, "current", 7)) {
+		inode = new_inode(dir->i_sb);
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		inode->i_mtime = inode->i_atime =
+			inode->i_ctime = CURRENT_TIME;
+		inode->i_ino = fake_ino(1, PROC_XID_INO);
+		inode->u.generic_ip = NULL;
+		inode->i_mode = S_IFLNK|S_IRWXUGO;
+		inode->i_uid = inode->i_gid = 0;
+		inode->i_size = 64;
+//		inode->i_op = &proc_current_inode_operations;
+		d_add(dentry, inode);
+		return NULL;
+	}
+	if (len == 4 && !memcmp(name, "info", 4)) {
+		inode = proc_xid_make_inode(dir->i_sb, NULL, PROC_XID_INFO);
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		inode->i_fop = &proc_xid_info_file_operations;
+		inode->u.proc_i.op.proc_xid_read = proc_virtual_info;
+		inode->i_mode = S_IFREG|S_IRUGO;
+//		inode->i_size = 64;
+//		inode->i_op = &proc_current_inode_operations;
+		d_add(dentry, inode);
+		return NULL;
+	}
+
+	while (len-- > 0) {
+		c = *name - '0';
+		name++;
+		if (c > 9)
+			goto out;
+		if (xid >= MAX_MULBY10)
+			goto out;
+		xid *= 10;
+		xid += c;
+		if (!xid)
+			goto out;
+	}
+
+	vxi = find_vx_info(xid);
+	if (!vxi)
+		goto out;
+
+	inode = NULL;
+	if (vx_check(xid, VX_ADMIN|VX_WATCH|VX_IDENT))
+		inode = proc_xid_make_inode(dir->i_sb,
+			vxi, PROC_XID_INO);
+	if (!inode)
+		goto out_release;
+
+	inode->i_mode = S_IFDIR|S_IRUGO;
+	inode->i_op = &proc_xid_inode_operations;
+	inode->i_fop = &proc_xid_operations;
+	inode->i_nlink = 4;
+	inode->i_flags|=S_IMMUTABLE;
+
+//	dentry->d_op = &xid_base_dentry_operations;
+	d_add(dentry, inode);
+	return NULL;
+	
+out_release:
+	put_vx_info(vxi);
+out:
+	return ERR_PTR(-ENOENT);
 }
 
-int vs_info_read_func(char *page, char **start,
-	off_t off, int count, int *eof, void *data)
+
+
+#define PROC_NUMBUF 10
+#define PROC_MAXXIDS 32
+
+
+static int get_xid_list(int index, unsigned int *xids)
 {
-	return __generic_info_read_func(page, start,
-	    off, count, eof, data, vs_proc_info);
-}
+	struct vx_info *p;
+	int nr_xids = 0;
 
+	index--;
+	spin_lock(&vxlist_lock);
+	list_for_each_entry(p, &vx_infos, vx_list) {
+		int xid = p->vx_id;
 
-static int __init virtual_proc_init(void)
+		if (--index >= 0)
+			continue;
+		xids[nr_xids] = xid;
+		if (++nr_xids >= PROC_MAXXIDS)
+			break;
+	}
+	spin_unlock(&vxlist_lock);
+	return nr_xids;
+}
+
+int proc_virtual_readdir(struct file * filp,
+	void * dirent, filldir_t filldir)
 {
-	proc_virtual_info = create_proc_read_entry("info",
-		S_IFREG|S_IRUGO|S_IWUSR,
-		proc_virtual, vs_info_read_func, NULL);
+	unsigned int xid_array[PROC_MAXXIDS];
+	char buf[PROC_NUMBUF];
+	unsigned int nr = filp->f_pos-3;
+	unsigned int nr_xids, i;
+	ino_t ino;
+
+	switch (filp->f_pos) {
+		case 0:
+			ino = fake_ino(0, PROC_XID_INO);
+			if (filldir(dirent, ".", 1,
+				filp->f_pos, ino, DT_DIR) < 0)
+				return 0;
+			filp->f_pos++;
+			/* fall through */
+		case 1:
+			ino = filp->f_dentry->d_parent->d_inode->i_ino;
+			if (filldir(dirent, "..", 2,
+				filp->f_pos, ino, DT_DIR) < 0)
+				return 0;
+			filp->f_pos++;
+			/* fall through */
+		case 2:
+			ino = fake_ino(0, PROC_XID_INFO);
+			if (filldir(dirent, "info", 4,
+				filp->f_pos, ino, DT_LNK) < 0)
+				return 0;
+			filp->f_pos++;
+			/* fall through */
+		case 3:
+			if (current->vx_id > 1) {
+				ino = fake_ino(1, PROC_XID_INO);
+				if (filldir(dirent, "current", 7,
+					filp->f_pos, ino, DT_LNK) < 0)
+					return 0;
+			}
+			filp->f_pos++;
+		default:
+	}
+
+	nr_xids = get_xid_list(nr, xid_array);
+
+	for (i = 0; i < nr_xids; i++) {
+		int xid = xid_array[i];
+		ino_t ino = fake_ino(xid, PROC_XID_INO);
+		unsigned long j = PROC_NUMBUF;
+
+		do buf[--j] = '0' + (xid % 10); while (xid/=10);
+
+		if (filldir(dirent, buf+j, PROC_NUMBUF-j,
+			filp->f_pos, ino, DT_DIR) < 0)
+			break;
+		filp->f_pos++;
+	}
 	return 0;
 }
 
-__initcall(virtual_proc_init);
+
+static struct file_operations proc_virtual_dir_operations = {
+	read:		generic_read_dir,
+	readdir:	proc_virtual_readdir,
+};
+
+static struct inode_operations proc_virtual_dir_inode_operations = {
+	lookup:		proc_virtual_lookup,
+};
+
+
+
+
+
+
+
+void proc_vx_init(void)
+{
+	struct proc_dir_entry *ent;
+
+	ent = proc_mkdir("virtual", 0);
+	if (ent) {
+		ent->proc_fops = &proc_virtual_dir_operations;
+		ent->proc_iops = &proc_virtual_dir_inode_operations;
+	}
+	proc_virtual = ent;
+}
+
+
+
+
+/* per pid info */
+
+
+char *task_vinfo(struct task_struct *p, char *buffer)
+{
+	return buffer + sprintf(buffer,
+		"VxID:\t%d\n"
+		,p->vx_id);
+}
+
+int proc_pid_vinfo(struct task_struct *p, char *buffer)
+{
+	char * orig = buffer;
+
+	buffer = task_vinfo(p, buffer);
+	return buffer - orig;
+}
+
--- linux-2.4.24-ck1-vs1.3.4/include/linux/capability.h	Tue Jan  6 07:08:16 2004
+++ linux-2.4.24-ck1-vs1.3.5/include/linux/capability.h	Wed Jan 14 02:06:46 2004
@@ -285,6 +285,11 @@ typedef __u32 kernel_cap_t;
 
 #define CAP_QUOTACTL         29
 
+/* Allow context manipulations */
+/* Allow changing context info on files */
+
+#define CAP_CONTEXT          30
+
 #ifdef __KERNEL__
 /* 
  * Bounding set
--- linux-2.4.24-ck1-vs1.3.4/include/linux/proc_fs.h	Tue Jan  6 07:09:46 2004
+++ linux-2.4.24-ck1-vs1.3.5/include/linux/proc_fs.h	Wed Jan 14 02:06:56 2004
@@ -58,7 +58,6 @@ struct proc_dir_entry {
 	nlink_t nlink;
 	uid_t uid;
 	gid_t gid;
-	xid_t xid;
 	int vx_flags;
 	unsigned long size;
 	struct inode_operations * proc_iops;
--- linux-2.4.24-ck1-vs1.3.4/include/linux/proc_fs_i.h	Tue Jan  6 07:06:59 2004
+++ linux-2.4.24-ck1-vs1.3.5/include/linux/proc_fs_i.h	Wed Jan 14 02:06:04 2004
@@ -1,3 +1,6 @@
+
+struct vx_info;
+
 struct proc_inode_info {
 	struct task_struct *task;
 	int type;
@@ -5,6 +8,7 @@ struct proc_inode_info {
 	union {
 		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
 		int (*proc_read)(struct task_struct *task, char *page);
+		int (*proc_xid_read)(struct vx_info *vxi, char *page);
 	} op;
 	struct file *file;
 };
--- linux-2.4.24-ck1-vs1.3.4/include/linux/vcontext.h	Tue Jan  6 07:07:51 2004
+++ linux-2.4.24-ck1-vs1.3.5/include/linux/vcontext.h	Wed Jan 14 02:06:46 2004
@@ -126,4 +126,10 @@ extern struct vx_info *find_vx_info(int)
 int vc_new_s_context(uint32_t, void *);
 int vc_set_ipv4root(uint32_t, void *);
 
+
+/* inode ioctls */
+
+#define	FIOC_GETXFLG	_IOR('x', 5, long)
+#define	FIOC_SETXFLG	_IOW('x', 6, long)
+
 #endif
--- linux-2.4.24-ck1-vs1.3.4/include/linux/vinline.h	Tue Jan  6 07:09:13 2004
+++ linux-2.4.24-ck1-vs1.3.5/include/linux/vinline.h	Wed Jan 14 02:06:46 2004
@@ -17,7 +17,6 @@
 void free_vx_info(struct vx_info *);
 
 extern int proc_pid_vinfo(struct task_struct *, char *);
-extern int vx_proc_destroy(struct vx_info *);
 
 
 #define get_vx_info(i)	__get_vx_info(i,__FILE__,__LINE__)
@@ -45,7 +44,6 @@ static __inline__ void __put_vx_info(str
 		vxi->vx_id, atomic_read(&vxi->vx_refcount),
 		_file, _line);
 	if (atomic_dec_and_lock(&vxi->vx_refcount, &vxlist_lock)) {
-		vx_proc_destroy(vxi);
 		list_del(&vxi->vx_list);
 		spin_unlock(&vxlist_lock);
 		free_vx_info(vxi);
@@ -86,6 +84,8 @@ static __inline__ void __vx_verify_info(
 
 #define vx_check(c,m)	__vx_check(vx_current_id(),c,m)
 
+#define vx_weak_check(c,m)	((m) ? vx_check(c,m) : 1)
+
 /*
  * check current context for ADMIN/WATCH and
  * optionally agains supplied argument
@@ -170,6 +170,11 @@ static __inline__ void __ip_verify_info(
 		ipa, ipb, _file, _line);
 }
 
+
+/* procfs ioctls */
+
+#define	FIOC_GETXFLG	_IOR('x', 5, long)
+#define	FIOC_SETXFLG	_IOW('x', 6, long)
 
 
 #endif
--- linux-2.4.24-ck1-vs1.3.4/kernel/vcontext.c	Tue Jan  6 07:06:57 2004
+++ linux-2.4.24-ck1-vs1.3.5/kernel/vcontext.c	Wed Jan 14 02:06:03 2004
@@ -272,8 +272,6 @@ static __inline__ xid_t __vx_dynamic_id(
 }
 
 
-extern int vx_proc_create(struct vx_info *);
-
 static struct vx_info *find_or_create_vx_info(int id)
 {
 	struct vx_info *new, *vxi = NULL;
@@ -303,9 +301,6 @@ static struct vx_info *find_or_create_vx
 	/* new context requested */
 	vxdprintk("find_or_create_vx_info(%d) = %p (new)\n", id, vxi);
 	atomic_set(&new->vx_refcount, 1);
-	if (vx_proc_create(new))
-		/* failed to create proc entry */
-		goto out_unlock;
 	list_add(&new->vx_list, &vx_infos);
 	vxi = new, new = NULL;
 
@@ -358,9 +353,12 @@ static int vx_migrate_task(struct task_s
 		goto out;
 
 	if (!(ret = vx_migrate_user(p, vxi))) {
-		if (old_vxi)
+		if (old_vxi) {
 			old_vxi->virt.nr_threads--;
+			atomic_dec(&old_vxi->limit.res[RLIMIT_NPROC]);
+		}		
 		vxi->virt.nr_threads++;
+		atomic_inc(&vxi->limit.res[RLIMIT_NPROC]);
 		p->vx_info = get_vx_info(vxi);
 		p->vx_id = vxi->vx_id;
 		if (old_vxi)
@@ -557,3 +555,50 @@ int vc_set_ipv4root(uint32_t nbip, void 
 	put_ip_info(ipi);
 	return 0;
 }
+
+
+#include <linux/proc_fs.h>
+
+int vx_proc_ioctl(struct inode * inode, struct file * filp,
+	unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *entry;
+	int error = 0;
+	int flags;
+
+	if (inode->i_ino < PROC_DYNAMIC_FIRST ||
+		inode->i_ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+		return -ENOTTY;
+
+	entry = (struct proc_dir_entry *) inode->u.generic_ip;
+
+	switch(cmd) {
+	case FIOC_GETXFLG: {
+		/* fixme: if stealth, return -ENOTTY */
+		error = -EPERM;
+		flags = entry->vx_flags;
+		if (capable(CAP_CONTEXT))
+			error = put_user(flags, (int *) arg);
+		break;
+	}
+	case FIOC_SETXFLG: {
+		/* fixme: if stealth, return -ENOTTY */
+		error = -EPERM;
+		if (!capable(CAP_CONTEXT))
+			break;
+		error = -EROFS;
+		if (IS_RDONLY(inode))
+			break;
+		error = -EFAULT;
+		if (get_user(flags, (int *) arg))
+			break;
+		error = 0;
+		entry->vx_flags = flags;
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return error;
+}
+
