--- linux-2.6.18.2/Documentation/vserver/debug.txt	1970-01-01 01:00:00 +0100
+++ linux-2.6.18.2-vs2.1.1/Documentation/vserver/debug.txt	2006-11-03 17:26:38 +0100
@@ -0,0 +1,154 @@
+
+debug_cvirt:
+
+ 2   4	"vx_map_tgid: %p/%llx: %d -> %d"
+	"vx_rmap_tgid: %p/%llx: %d -> %d"
+
+debug_dlim:
+
+ 0   1	"ALLOC (%p,#%d)%c inode (%d)"
+	"FREE  (%p,#%d)%c inode"
+ 1   2	"ALLOC (%p,#%d)%c %lld bytes (%d)"
+	"FREE  (%p,#%d)%c %lld bytes"
+ 2   4	"ADJUST: %lld,%lld on %ld,%ld [mult=%d]"
+ 3   8	"ext3_has_free_blocks(%p): %lu<%lu+1, %c, %u!=%u r=%d"
+	"ext3_has_free_blocks(%p): free=%lu, root=%lu"
+	"rcu_free_dl_info(%p)"
+ 4  10	"alloc_dl_info(%p,%d) = %p"
+	"dealloc_dl_info(%p)"
+	"get_dl_info(%p[#%d.%d])"
+	"put_dl_info(%p[#%d.%d])"
+ 5  20	"alloc_dl_info(%p,%d)*"
+ 6  40	"__hash_dl_info: %p[#%d]"
+	"__unhash_dl_info: %p[#%d]"
+ 7  80	"locate_dl_info(%p,#%d) = %p"
+
+debug_misc:
+
+ 0   1	"destroy_dqhash: %p [#0x%08x] c=%d"
+	"new_dqhash: %p [#0x%08x]"
+	"vroot[%d]_clr_dev: dev=%p[%lu,%d:%d]"
+	"vroot[%d]_get_real_bdev: dev=%p[%lu,%d:%d]"
+	"vroot[%d]_set_dev: dev=%p[%lu,%d:%d]"
+	"vroot_get_real_bdev not set"
+ 1   2	"cow_break_link(»%s«)"
+	"temp copy »%s«"
+ 2   4	"dentry_open(new): %p"
+	"dentry_open(old): %p"
+	"lookup_create(new): %p"
+	"old path »%s«"
+	"path_lookup(old): %d"
+	"vfs_create(new): %d"
+	"vfs_rename: %d"
+	"vfs_sendfile: %d"
+ 3   8	"fput(new_file=%p[#%d])"
+	"fput(old_file=%p[#%d])"
+ 4  10	"vx_info_kill(%p[#%d],%d,%d) = %d"
+	"vx_info_kill(%p[#%d],%d,%d)*"
+ 5  20	"vs_reboot(%p[#%d],%d)"
+ 6  40	"dropping task %p[#%u,%u] for %p[#%u,%u]"
+
+debug_net:
+
+ 2   4	"nx_addr_conflict(%p,%p) %d.%d,%d.%d"
+ 3   8	"inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d"
+	"inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d"
+ 4  10	"ip_route_connect(%p) %p,%p;%lx"
+ 5  20	"__addr_in_socket(%p,%d.%d.%d.%d) %p:%d.%d.%d.%d %p;%lx"
+ 6  40	"sk,egf: %p [#%d] (from %d)"
+	"sk,egn: %p [#%d] (from %d)"
+	"sk,req: %p [#%d] (from %d)"
+	"sk: %p [#%d] (from %d)"
+	"tw: %p [#%d] (from %d)"
+ 7  80	"__sock_recvmsg: %p[%p,%p,%p;%d]:%d/%d"
+	"__sock_sendmsg: %p[%p,%p,%p;%d]:%d/%d"
+
+debug_nid:
+
+ 0   1	"__lookup_nx_info(#%u): %p[#%u]"
+	"alloc_nx_info(%d) = %p"
+	"create_nx_info(%d) (dynamic rejected)"
+	"create_nx_info(%d) = %p (already there)"
+	"create_nx_info(%d) = %p (new)"
+	"dealloc_nx_info(%p)"
+ 1   2	"alloc_nx_info(%d)*"
+	"create_nx_info(%d)*"
+ 2   4	"get_nx_info(%p[#%d.%d])"
+	"put_nx_info(%p[#%d.%d])"
+ 3   8	"claim_nx_info(%p[#%d.%d.%d]) %p"
+	"clr_nx_info(%p[#%d.%d])"
+	"init_nx_info(%p[#%d.%d])"
+	"release_nx_info(%p[#%d.%d.%d]) %p"
+	"set_nx_info(%p[#%d.%d])"
+ 4  10	"__hash_nx_info: %p[#%d]"
+	"__nx_dynamic_id: [#%d]"
+	"__unhash_nx_info: %p[#%d]"
+ 5  20	"moved task %p into nxi:%p[#%d]"
+	"nx_migrate_task(%p,%p[#%d.%d.%d])"
+	"task_get_nx_info(%p)"
+ 6  40	"nx_clear_persistent(%p[#%d])"
+
+debug_quota:
+
+ 0   1	"quota_sync_dqh(%p,%d) discard inode %p"
+ 1   2	"quota_sync_dqh(%p,%d)"
+	"sync_dquots(%p,%d)"
+	"sync_dquots_dqh(%p,%d)"
+ 3   8	"do_quotactl(%p,%d,cmd=%d,id=%d,%p)"
+
+debug_switch:
+
+ 0   1	"vc: VCMD_%02d_%d[%d], %d,%p [%d,%d,%x,%x]"
+ 1   2	"vc: VCMD_%02d_%d[%d] = %08lx(%ld) [%d,%d]"
+ 4  10	"%s: (%s %s) returned %s with %d"
+
+debug_tag:
+
+ 7  80	"dx_parse_tag(»%s«): %d:#%d"
+	"dx_propagate_tag(%p[#%lu.%d]): %d,%d"
+
+debug_xid:
+
+ 0   1	"__lookup_vx_info(#%u): %p[#%u]"
+	"alloc_vx_info(%d) = %p"
+	"alloc_vx_info(%d)*"
+	"create_vx_info(%d) (dynamic rejected)"
+	"create_vx_info(%d) = %p (already there)"
+	"create_vx_info(%d) = %p (new)"
+	"dealloc_vx_info(%p)"
+	"loc_vx_info(%d) = %p (found)"
+	"loc_vx_info(%d) = %p (new)"
+	"loc_vx_info(%d) = %p (not available)"
+ 1   2	"create_vx_info(%d)*"
+	"loc_vx_info(%d)*"
+ 2   4	"get_vx_info(%p[#%d.%d])"
+	"put_vx_info(%p[#%d.%d])"
+ 3   8	"claim_vx_info(%p[#%d.%d.%d]) %p"
+	"clr_vx_info(%p[#%d.%d])"
+	"init_vx_info(%p[#%d.%d])"
+	"release_vx_info(%p[#%d.%d.%d]) %p"
+	"set_vx_info(%p[#%d.%d])"
+	"vx_child_reaper(%p[#%u,%u]) = %p[#%u,%u]"
+ 4  10	"__hash_vx_info: %p[#%d]"
+	"__unhash_vx_info: %p[#%d]"
+	"__vx_dynamic_id: [#%d]"
+ 5  20	"enter_vx_info(%p[#%d],%p) %p[#%d,%p]"
+	"leave_vx_info(%p[#%d,%p]) %p[#%d,%p]"
+	"moved task %p into vxi:%p[#%d]"
+	"task_get_vx_info(%p)"
+	"vx_migrate_task(%p,%p[#%d.%d])"
+ 6  40	"vx_clear_persistent(%p[#%d])"
+	"vx_exit_init(%p[#%d],%p[#%d,%d,%d])"
+	"vx_set_init(%p[#%d],%p[#%d,%d,%d])"
+	"vx_set_persistent(%p[#%d])"
+	"vx_set_reaper(%p[#%d],%p[#%d,%d])"
+
+
+debug_limit:
+
+ n 2^n	"vx_acc_cres[%5d,%s,%2d]: %5d%s"
+	"vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
+
+ m 2^m	"vx_acc_page[%5d,%s,%2d]: %5d%s"
+	"vx_acc_pages[%5d,%s,%2d]: %5d += %5d"
+	"vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
--- linux-2.6.18.2/arch/i386/kernel/traps.c	2006-09-20 16:57:58 +0200
+++ linux-2.6.18.2-vs2.1.1/arch/i386/kernel/traps.c	2006-09-25 15:40:02 +0200
@@ -388,6 +390,8 @@ void die(const char * str, struct pt_reg
 
 	oops_enter();
 
+	vxh_throw_oops();
+
 	if (die.lock_owner != raw_smp_processor_id()) {
 		console_verbose();
 		spin_lock_irqsave(&die.lock, flags);
--- linux-2.6.18.2/arch/i386/kernel/traps.c	2006-09-20 16:57:58 +0200
+++ linux-2.6.18.2-vs2.1.1/arch/i386/kernel/traps.c	2006-09-25 15:40:02 +0200
@@ -424,9 +428,9 @@ void die(const char * str, struct pt_reg
 		if (nl)
 			printk("\n");
 		if (notify_die(DIE_OOPS, str, regs, err,
-					current->thread.trap_no, SIGSEGV) !=
-				NOTIFY_STOP) {
+			current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
 			show_registers(regs);
+			vxh_dump_history();
 			/* Executive summary in case the oops scrolled away */
 			esp = (unsigned long) (&regs->esp);
 			savesegment(ss, ss);
--- linux-2.6.18.2/drivers/char/sysrq.c	2006-09-20 16:58:13 +0200
+++ linux-2.6.18.2-vs2.1.1/drivers/char/sysrq.c	2006-09-25 15:40:02 +0200
@@ -271,6 +272,21 @@ static struct sysrq_key_op sysrq_unrt_op
 	.enable_mask	= SYSRQ_ENABLE_RTNICE,
 };
 
+
+#ifdef CONFIG_VSERVER_DEBUG
+static void sysrq_handle_vxinfo(int key, struct pt_regs *pt_regs,
+				 struct tty_struct *tty)
+{
+	dump_vx_info_inactive((key == 'x')?0:1);
+}
+static struct sysrq_key_op sysrq_showvxinfo_op = {
+	.handler	= sysrq_handle_vxinfo,
+	.help_msg	= "conteXt",
+	.action_msg	= "Show Context Info",
+	.enable_mask	= SYSRQ_ENABLE_DUMP,
+};
+#endif
+
 /* Key Operations table and lock */
 static DEFINE_SPINLOCK(sysrq_key_table_lock);
 
--- linux-2.6.18.2/drivers/char/sysrq.c	2006-09-20 16:58:13 +0200
+++ linux-2.6.18.2-vs2.1.1/drivers/char/sysrq.c	2006-09-25 15:40:02 +0200
@@ -315,7 +331,11 @@ static struct sysrq_key_op *sysrq_key_ta
 	/* May be assigned at init time by SMP VOYAGER */
 	NULL,				/* v */
 	NULL,				/* w */
+#ifdef CONFIG_VSERVER_DEBUG
+	&sysrq_showvxinfo_op,		/* x */
+#else
 	NULL,				/* x */
+#endif
 	NULL,				/* y */
 	NULL				/* z */
 };
--- linux-2.6.18.2/drivers/char/sysrq.c	2006-09-20 16:58:13 +0200
+++ linux-2.6.18.2-vs2.1.1/drivers/char/sysrq.c	2006-09-25 15:40:02 +0200
@@ -329,6 +349,8 @@ static int sysrq_key_table_key2index(int
 		retval = key - '0';
 	else if ((key >= 'a') && (key <= 'z'))
 		retval = key + 10 - 'a';
+	else if ((key >= 'A') && (key <= 'Z'))
+		retval = key + 10 - 'A';
 	else
 		retval = -1;
 	return retval;
--- linux-2.6.18.2/include/linux/vserver/debug.h	1970-01-01 01:00:00 +0100
+++ linux-2.6.18.2-vs2.1.1/include/linux/vserver/debug.h	2006-11-03 18:16:21 +0100
@@ -0,0 +1,112 @@
+#ifndef _VX_DEBUG_H
+#define _VX_DEBUG_H
+
+
+#define VXD_CBIT(n,m)	(vx_debug_ ## n & (1 << (m)))
+#define VXD_CMIN(n,m)	(vx_debug_ ## n > (m))
+#define VXD_MASK(n,m)	(vx_debug_ ## n & (m))
+
+#define VXD_QPOS(v,p)	(((uint32_t)(v) >> ((p)*8)) & 0xFF)
+#define VXD_QUAD(v)	VXD_QPOS(v,0), VXD_QPOS(v,1),		\
+			VXD_QPOS(v,2), VXD_QPOS(v,3)
+#define VXF_QUAD	"%u.%u.%u.%u"
+
+#define VXD_DEV(d)	(d), (d)->bd_inode->i_ino,		\
+			imajor((d)->bd_inode), iminor((d)->bd_inode)
+#define VXF_DEV		"%p[%lu,%d:%d]"
+
+
+#define __FUNC__	__func__
+
+
+#ifdef	CONFIG_VSERVER_DEBUG
+
+extern unsigned int vx_debug_switch;
+extern unsigned int vx_debug_xid;
+extern unsigned int vx_debug_nid;
+extern unsigned int vx_debug_tag;
+extern unsigned int vx_debug_net;
+extern unsigned int vx_debug_limit;
+extern unsigned int vx_debug_cres;
+extern unsigned int vx_debug_dlim;
+extern unsigned int vx_debug_quota;
+extern unsigned int vx_debug_cvirt;
+extern unsigned int vx_debug_misc;
+
+
+#define VX_LOGLEVEL	"vxD: "
+#define VX_WARNLEVEL	KERN_WARNING "vxW: "
+
+#define vxdprintk(c,f,x...)					\
+	do {							\
+		if (c)						\
+			printk(VX_LOGLEVEL f "\n" , ##x);	\
+	} while (0)
+
+#define vxlprintk(c,f,x...)					\
+	do {							\
+		if (c)						\
+			printk(VX_LOGLEVEL f " @%s:%d\n", x);	\
+	} while (0)
+
+#define vxfprintk(c,f,x...)					\
+	do {							\
+		if (c)						\
+			printk(VX_LOGLEVEL f " %s@%s:%d\n", x); \
+	} while (0)
+
+
+#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)); })
+
+#define vxd_cond_path(n)					\
+	((n) ? vxd_path((n)->dentry, (n)->mnt) : "<null>" )
+
+
+struct vx_info;
+
+void dump_vx_info(struct vx_info *, int);
+void dump_vx_info_inactive(int);
+
+#else	/* CONFIG_VSERVER_DEBUG */
+
+#define vx_debug_switch 0
+#define vx_debug_xid	0
+#define vx_debug_nid	0
+#define vx_debug_tag	0
+#define vx_debug_net	0
+#define vx_debug_limit	0
+#define vx_debug_cres	0
+#define vx_debug_dlim	0
+#define vx_debug_cvirt	0
+
+#define vxdprintk(x...) do { } while (0)
+#define vxlprintk(x...) do { } while (0)
+#define vxfprintk(x...) do { } while (0)
+#define vxwprintk(x...) do { } while (0)
+
+#define vxd_path	"<none>"
+#define vxd_cond_path	vxd_path
+
+#endif	/* CONFIG_VSERVER_DEBUG */
+
+
+#ifdef	CONFIG_VSERVER_DEBUG
+#define vxd_assert_lock(l)	assert_spin_locked(l)
+#define vxd_assert(c,f,x...)	vxlprintk(!(c), \
+	"assertion [" f "] failed.", ##x, __FILE__, __LINE__)
+#else
+#define vxd_assert_lock(l)	do { } while (0)
+#define vxd_assert(c,f,x...)	do { } while (0)
+#endif
+
+
+#endif /* _VX_DEBUG_H */
--- linux-2.6.18.2/include/linux/vserver/history.h	1970-01-01 01:00:00 +0100
+++ linux-2.6.18.2-vs2.1.1/include/linux/vserver/history.h	2006-10-07 17:50:52 +0200
@@ -0,0 +1,197 @@
+#ifndef _VX_HISTORY_H
+#define _VX_HISTORY_H
+
+
+enum {
+	VXH_UNUSED=0,
+	VXH_THROW_OOPS=1,
+
+	VXH_GET_VX_INFO,
+	VXH_PUT_VX_INFO,
+	VXH_INIT_VX_INFO,
+	VXH_SET_VX_INFO,
+	VXH_CLR_VX_INFO,
+	VXH_CLAIM_VX_INFO,
+	VXH_RELEASE_VX_INFO,
+	VXH_ALLOC_VX_INFO,
+	VXH_DEALLOC_VX_INFO,
+	VXH_HASH_VX_INFO,
+	VXH_UNHASH_VX_INFO,
+	VXH_LOC_VX_INFO,
+	VXH_LOOKUP_VX_INFO,
+	VXH_CREATE_VX_INFO,
+};
+
+struct _vxhe_vxi {
+	struct vx_info *ptr;
+	unsigned xid;
+	unsigned usecnt;
+	unsigned tasks;
+};
+
+struct _vxhe_set_clr {
+	void *data;
+};
+
+struct _vxhe_loc_lookup {
+	unsigned arg;
+};
+
+struct _vx_hist_entry {
+	void *loc;
+	unsigned short seq;
+	unsigned short type;
+	struct _vxhe_vxi vxi;
+	union {
+		struct _vxhe_set_clr sc;
+		struct _vxhe_loc_lookup ll;
+	};
+};
+
+#ifdef	CONFIG_VSERVER_HISTORY
+
+extern unsigned volatile int vxh_active;
+
+struct _vx_hist_entry *vxh_advance(void *loc);
+
+
+static inline
+void	__vxh_copy_vxi(struct _vx_hist_entry *entry, struct vx_info *vxi)
+{
+	entry->vxi.ptr = vxi;
+	if (vxi) {
+		entry->vxi.usecnt = atomic_read(&vxi->vx_usecnt);
+		entry->vxi.tasks = atomic_read(&vxi->vx_tasks);
+		entry->vxi.xid = vxi->vx_id;
+	}
+}
+
+
+#define	__HERE__ current_text_addr()
+
+#define __VXH_BODY(__type, __data, __here)	\
+	struct _vx_hist_entry *entry;		\
+						\
+	preempt_disable();			\
+	entry = vxh_advance(__here);		\
+	__data;					\
+	entry->type = __type;			\
+	preempt_enable();
+
+
+	/* pass vxi only */
+
+#define __VXH_SMPL				\
+	__vxh_copy_vxi(entry, vxi)
+
+static inline
+void	__vxh_smpl(struct vx_info *vxi, int __type, void *__here)
+{
+	__VXH_BODY(__type, __VXH_SMPL, __here)
+}
+
+	/* pass vxi and data (void *) */
+
+#define __VXH_DATA				\
+	__vxh_copy_vxi(entry, vxi);		\
+	entry->sc.data = data
+
+static inline
+void	__vxh_data(struct vx_info *vxi, void *data,
+			int __type, void *__here)
+{
+	__VXH_BODY(__type, __VXH_DATA, __here)
+}
+
+	/* pass vxi and arg (long) */
+
+#define __VXH_LONG				\
+	__vxh_copy_vxi(entry, vxi);		\
+	entry->ll.arg = arg
+
+static inline
+void	__vxh_long(struct vx_info *vxi, long arg,
+			int __type, void *__here)
+{
+	__VXH_BODY(__type, __VXH_LONG, __here)
+}
+
+
+static inline
+void	__vxh_throw_oops(void *__here)
+{
+	__VXH_BODY(VXH_THROW_OOPS, {}, __here);
+	/* prevent further acquisition */
+	vxh_active = 0;
+}
+
+
+#define vxh_throw_oops()	__vxh_throw_oops(__HERE__);
+
+#define __vxh_get_vx_info(v,h)	__vxh_smpl(v, VXH_GET_VX_INFO, h);
+#define __vxh_put_vx_info(v,h)	__vxh_smpl(v, VXH_PUT_VX_INFO, h);
+
+#define __vxh_init_vx_info(v,d,h) \
+	__vxh_data(v,d, VXH_INIT_VX_INFO, h);
+#define __vxh_set_vx_info(v,d,h) \
+	__vxh_data(v,d, VXH_SET_VX_INFO, h);
+#define __vxh_clr_vx_info(v,d,h) \
+	__vxh_data(v,d, VXH_CLR_VX_INFO, h);
+
+#define __vxh_claim_vx_info(v,d,h) \
+	__vxh_data(v,d, VXH_CLAIM_VX_INFO, h);
+#define __vxh_release_vx_info(v,d,h) \
+	__vxh_data(v,d, VXH_RELEASE_VX_INFO, h);
+
+#define vxh_alloc_vx_info(v) \
+	__vxh_smpl(v, VXH_ALLOC_VX_INFO, __HERE__);
+#define vxh_dealloc_vx_info(v) \
+	__vxh_smpl(v, VXH_DEALLOC_VX_INFO, __HERE__);
+
+#define vxh_hash_vx_info(v) \
+	__vxh_smpl(v, VXH_HASH_VX_INFO, __HERE__);
+#define vxh_unhash_vx_info(v) \
+	__vxh_smpl(v, VXH_UNHASH_VX_INFO, __HERE__);
+
+#define vxh_loc_vx_info(v,l) \
+	__vxh_long(v,l, VXH_LOC_VX_INFO, __HERE__);
+#define vxh_lookup_vx_info(v,l) \
+	__vxh_long(v,l, VXH_LOOKUP_VX_INFO, __HERE__);
+#define vxh_create_vx_info(v,l) \
+	__vxh_long(v,l, VXH_CREATE_VX_INFO, __HERE__);
+
+extern void vxh_dump_history(void);
+
+
+#else  /* CONFIG_VSERVER_HISTORY */
+
+#define	__HERE__	0
+
+#define vxh_throw_oops()		do { } while (0)
+
+#define __vxh_get_vx_info(v,h)		do { } while (0)
+#define __vxh_put_vx_info(v,h)		do { } while (0)
+
+#define __vxh_init_vx_info(v,d,h)	do { } while (0)
+#define __vxh_set_vx_info(v,d,h)	do { } while (0)
+#define __vxh_clr_vx_info(v,d,h)	do { } while (0)
+
+#define __vxh_claim_vx_info(v,d,h)	do { } while (0)
+#define __vxh_release_vx_info(v,d,h)	do { } while (0)
+
+#define vxh_alloc_vx_info(v)		do { } while (0)
+#define vxh_dealloc_vx_info(v)		do { } while (0)
+
+#define vxh_hash_vx_info(v)		do { } while (0)
+#define vxh_unhash_vx_info(v)		do { } while (0)
+
+#define vxh_loc_vx_info(a,v)		do { } while (0)
+#define vxh_lookup_vx_info(a,v)		do { } while (0)
+#define vxh_create_vx_info(a,v)		do { } while (0)
+
+#define vxh_dump_history()		do { } while (0)
+
+
+#endif /* CONFIG_VSERVER_HISTORY */
+
+#endif /* _VX_HISTORY_H */
--- linux-2.6.18.2/kernel/vserver/debug.c	1970-01-01 01:00:00 +0100
+++ linux-2.6.18.2-vs2.1.1/kernel/vserver/debug.c	2006-09-25 15:40:02 +0200
@@ -0,0 +1,37 @@
+/*
+ *  kernel/vserver/debug.c
+ *
+ *  Copyright (C) 2005  Herbert Pötzl
+ *
+ *  V0.01  vx_info dump support
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/vserver/cvirt_def.h>
+#include <linux/vserver/cacct_def.h>
+#include <linux/vserver/limit_def.h>
+#include <linux/vserver/sched_def.h>
+
+
+void	dump_vx_info(struct vx_info *vxi, int level)
+{
+	printk("vx_info %p[#%d, %d.%d, %4x]\n", vxi, vxi->vx_id,
+		atomic_read(&vxi->vx_usecnt),
+		atomic_read(&vxi->vx_tasks),
+		vxi->vx_state);
+	if (level > 0) {
+		__dump_vx_limit(&vxi->limit);
+		__dump_vx_sched(&vxi->sched);
+		__dump_vx_cvirt(&vxi->cvirt);
+		__dump_vx_cacct(&vxi->cacct);
+	}
+	printk("---\n");
+}
+
+
+EXPORT_SYMBOL_GPL(dump_vx_info);
+
--- linux-2.6.18.2/kernel/vserver/history.c	1970-01-01 01:00:00 +0100
+++ linux-2.6.18.2-vs2.1.1/kernel/vserver/history.c	2006-10-20 03:18:58 +0200
@@ -0,0 +1,263 @@
+/*
+ *  kernel/vserver/history.c
+ *
+ *  Virtual Context History Backtrace
+ *
+ *  Copyright (C) 2004-2005  Herbert Pötzl
+ *
+ *  V0.01  basic structure
+ *  V0.02  hash/unhash and trace
+ *  V0.03  preemption fixes
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/unistd.h>
+
+#include <linux/vserver/debug.h>
+#include <linux/vserver/debug_cmd.h>
+#include <linux/vserver/history.h>
+
+
+#ifdef	CONFIG_VSERVER_HISTORY
+#define VXH_SIZE	CONFIG_VSERVER_HISTORY_SIZE
+#else
+#define VXH_SIZE	64
+#endif
+
+struct _vx_history {
+	unsigned int counter;
+
+	struct _vx_hist_entry entry[VXH_SIZE+1];
+};
+
+
+DEFINE_PER_CPU(struct _vx_history, vx_history_buffer);
+
+unsigned volatile int vxh_active = 1;
+
+static atomic_t sequence = ATOMIC_INIT(0);
+
+
+/*	vxh_advance()
+
+	* requires disabled preemption				*/
+
+struct _vx_hist_entry *vxh_advance(void *loc)
+{
+	unsigned int cpu = smp_processor_id();
+	struct _vx_history *hist = &per_cpu(vx_history_buffer, cpu);
+	struct _vx_hist_entry *entry;
+	unsigned int index;
+
+	index = vxh_active ? (hist->counter++ % VXH_SIZE) : VXH_SIZE;
+	entry = &hist->entry[index];
+
+	entry->seq = atomic_inc_return(&sequence);
+	entry->loc = loc;
+	return entry;
+}
+
+EXPORT_SYMBOL_GPL(vxh_advance);
+
+
+#define VXH_LOC_FMTS	"(#%04x,*%d):%p"
+
+#define VXH_LOC_ARGS(e)	(e)->seq, cpu, (e)->loc
+
+
+#define VXH_VXI_FMTS	"%p[#%d,%d.%d]"
+
+#define VXH_VXI_ARGS(e)	(e)->vxi.ptr,			\
+			(e)->vxi.ptr?(e)->vxi.xid:0,	\
+			(e)->vxi.ptr?(e)->vxi.usecnt:0,	\
+			(e)->vxi.ptr?(e)->vxi.tasks:0
+
+void	vxh_dump_entry(struct _vx_hist_entry *e, unsigned cpu)
+{
+	switch (e->type) {
+	case VXH_THROW_OOPS:
+		printk( VXH_LOC_FMTS " oops \n", VXH_LOC_ARGS(e));
+		break;
+
+	case VXH_GET_VX_INFO:
+	case VXH_PUT_VX_INFO:
+		printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS "\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_GET_VX_INFO)?"get":"put",
+			VXH_VXI_ARGS(e));
+		break;
+
+	case VXH_INIT_VX_INFO:
+	case VXH_SET_VX_INFO:
+	case VXH_CLR_VX_INFO:
+		printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS " @%p\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_INIT_VX_INFO)?"init":
+			((e->type==VXH_SET_VX_INFO)?"set":"clr"),
+			VXH_VXI_ARGS(e), e->sc.data);
+		break;
+
+	case VXH_CLAIM_VX_INFO:
+	case VXH_RELEASE_VX_INFO:
+		printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS " @%p\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_CLAIM_VX_INFO)?"claim":"release",
+			VXH_VXI_ARGS(e), e->sc.data);
+		break;
+
+	case VXH_ALLOC_VX_INFO:
+	case VXH_DEALLOC_VX_INFO:
+		printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS "\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_ALLOC_VX_INFO)?"alloc":"dealloc",
+			VXH_VXI_ARGS(e));
+		break;
+
+	case VXH_HASH_VX_INFO:
+	case VXH_UNHASH_VX_INFO:
+		printk( VXH_LOC_FMTS " __%s_vx_info " VXH_VXI_FMTS "\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_HASH_VX_INFO)?"hash":"unhash",
+			VXH_VXI_ARGS(e));
+		break;
+
+	case VXH_LOC_VX_INFO:
+	case VXH_LOOKUP_VX_INFO:
+	case VXH_CREATE_VX_INFO:
+		printk( VXH_LOC_FMTS " __%s_vx_info [#%d] -> " VXH_VXI_FMTS "\n",
+			VXH_LOC_ARGS(e),
+			(e->type==VXH_CREATE_VX_INFO)?"create":
+			((e->type==VXH_LOC_VX_INFO)?"loc":"lookup"),
+			e->ll.arg, VXH_VXI_ARGS(e));
+		break;
+	}
+}
+
+static void __vxh_dump_history(void)
+{
+	unsigned int i, cpu;
+
+	printk("History:\tSEQ: %8x\tNR_CPUS: %d\n",
+		atomic_read(&sequence), NR_CPUS);
+
+	for (i=0; i < VXH_SIZE; i++) {
+		for_each_online_cpu(cpu) {
+			struct _vx_history *hist =
+				&per_cpu(vx_history_buffer, cpu);
+			unsigned int index = (hist->counter-i) % VXH_SIZE;
+			struct _vx_hist_entry *entry = &hist->entry[index];
+
+			vxh_dump_entry(entry, cpu);
+		}
+	}
+}
+
+void	vxh_dump_history(void)
+{
+	vxh_active = 0;
+#ifdef CONFIG_SMP
+	local_irq_enable();
+	smp_send_stop();
+	local_irq_disable();
+#endif
+	__vxh_dump_history();
+}
+
+
+/* vserver syscall commands below here */
+
+
+int vc_dump_history(uint32_t id)
+{
+	vxh_active = 0;
+	__vxh_dump_history();
+	vxh_active = 1;
+
+	return 0;
+}
+
+
+int do_read_history(struct __user _vx_hist_entry *data,
+	int cpu, uint32_t *index, uint32_t *count)
+{
+	int pos, ret = 0;
+	struct _vx_history *hist = &per_cpu(vx_history_buffer, cpu);
+	int end = hist->counter;
+	int start = end - VXH_SIZE + 2;
+	int idx = *index;
+
+	/* special case: get current pos */
+	if (!*count) {
+		*index = end;
+		return 0;
+	}
+
+	/* have we lost some data? */
+	if (idx < start)
+		idx = start;
+
+	for (pos = 0; (pos < *count) && (idx < end); pos++, idx++) {
+		struct _vx_hist_entry *entry =
+			&hist->entry[idx % VXH_SIZE];
+
+		/* send entry to userspace */
+		ret = copy_to_user (&data[pos], entry, sizeof(*entry));
+		if (ret)
+			break;
+	}
+	/* save new index and count */
+	*index = idx;
+	*count = pos;
+	return ret ? ret : (*index < end);
+}
+
+int vc_read_history(uint32_t id, void __user *data)
+{
+	struct vcmd_read_history_v0 vc_data;
+	int ret;
+
+	if (id >= NR_CPUS)
+		return -EINVAL;
+
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = do_read_history((struct __user _vx_hist_entry *)vc_data.data,
+		id, &vc_data.index, &vc_data.count);
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		return -EFAULT;
+	return ret;
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_read_history_x32(uint32_t id, void __user *data)
+{
+	struct vcmd_read_history_v0_x32 vc_data;
+	int ret;
+
+	if (id >= NR_CPUS)
+		return -EINVAL;
+
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = do_read_history((struct __user _vx_hist_entry *)
+		compat_ptr(vc_data.data_ptr),
+		id, &vc_data.index, &vc_data.count);
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		return -EFAULT;
+	return ret;
+}
+
+#endif	/* CONFIG_COMPAT */
+
