diff -u linux-2.6.9-vs1.9.3-w03/include/linux/vs_context.h linux-2.6.9-vs1.9.3-w03/include/linux/vs_context.h
--- linux-2.6.9-vs1.9.3-w03/include/linux/vs_context.h	2005-01-13 13:19:35.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/include/linux/vs_context.h	2005-01-13 13:19:35.000000000 +0100
@@ -17,6 +17,8 @@
 	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);
+	vxh_get_vx_info(vxi);
+
 	atomic_inc(&vxi->vx_usecnt);
 	return vxi;
 }
@@ -31,6 +33,8 @@
 	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);
+	vxh_put_vx_info(vxi);
+
 	if (atomic_dec_and_test(&vxi->vx_usecnt))
 		free_vx_info(vxi);
 }
@@ -50,6 +54,7 @@
 		vxi?atomic_read(&vxi->vx_usecnt):0,
 		vxi?atomic_read(&vxi->vx_refcnt):0,
 		_file, _line);
+	vxh_set_vx_info(vxi, vxp);
 
 	atomic_inc(&vxi->vx_refcnt);
 	vxo = xchg(vxp, __get_vx_info(vxi, _file, _line));
@@ -72,6 +77,7 @@
 		vxo?atomic_read(&vxo->vx_usecnt):0,
 		vxo?atomic_read(&vxo->vx_refcnt):0,
 		_file, _line);
+	vxh_clr_vx_info(vxo, vxp);
 
 	if (atomic_dec_and_test(&vxo->vx_refcnt))
 		unhash_vx_info(vxo);
diff -u linux-2.6.9-vs1.9.3-w03/include/linux/vserver/debug.h linux-2.6.9-vs1.9.3-w03/include/linux/vserver/debug.h
--- linux-2.6.9-vs1.9.3-w03/include/linux/vserver/debug.h	2005-01-13 13:19:35.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/include/linux/vserver/debug.h	2005-01-13 13:19:35.000000000 +0100
@@ -72,7 +72,198 @@
 #define vxfprintk(x...) do { } while (0)
 
-#endif
+#define vxwprintk(x...) do { } while (0)
 
+#define vxd_path	"<none>"
 
+#endif	/* CONFIG_VSERVER_DEBUG */
+
+
+/* history stuff */
+
+#ifdef	CONFIG_VSERVER_HISTORY
+
+
+extern unsigned volatile int vxh_active;
+
+struct _vxhe_vxi {
+	struct vx_info *ptr;
+	unsigned xid;
+	unsigned usecnt;
+	unsigned refcnt;
+};
+
+struct _vxhe_set_clr {
+	void *data;
+};
+
+struct _vxhe_loc_lookup {
+	unsigned arg;
+};
+
+enum {
+	VXH_UNUSED=0,
+	VXH_THROW_OOPS=1,
+
+	VXH_GET_VX_INFO,
+	VXH_PUT_VX_INFO,
+	VXH_SET_VX_INFO,
+	VXH_CLR_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,
+};
+
+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;
+	};
+};
+
+struct _vx_hist_entry *vxh_advance(void *loc);
+
+#define	VXH_HERE()		\
+	({ __label__ here;	\
+		here:;		\
+		&&here; })
+
+
+
+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.refcnt = atomic_read(&vxi->vx_refcnt);
+		entry->vxi.xid = vxi->vx_id;
+	}
+}
+
+static inline void vxh_throw_oops(void)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	entry->type = VXH_THROW_OOPS;
+
+	/* prevent further acquisition */
+	vxh_active = 0;
+}
+
+static inline void vxh_get_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_GET_VX_INFO;
+}
+
+static inline void vxh_put_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_PUT_VX_INFO;
+}
+
+static inline void vxh_set_vx_info(struct vx_info *vxi, void *data)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->sc.data = data;
+	entry->type = VXH_SET_VX_INFO;
+}
+
+static inline void vxh_clr_vx_info(struct vx_info *vxi, void *data)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->sc.data = data;
+	entry->type = VXH_CLR_VX_INFO;
+}
+
+static inline void vxh_alloc_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_ALLOC_VX_INFO;
+}
+
+static inline void vxh_dealloc_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_DEALLOC_VX_INFO;
+}
+
+static inline void vxh_hash_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_HASH_VX_INFO;
+}
+
+static inline void vxh_unhash_vx_info(struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->type = VXH_UNHASH_VX_INFO;
+}
+
+static inline void vxh_loc_vx_info(unsigned arg, struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->ll.arg = arg;
+	entry->type = VXH_LOC_VX_INFO;
+}
+
+static inline void vxh_lookup_vx_info(unsigned arg, struct vx_info *vxi)
+{
+	struct _vx_hist_entry *entry = vxh_advance(VXH_HERE());
+
+	__vxh_copy_vxi(entry, vxi);
+	entry->ll.arg = arg;
+	entry->type = VXH_LOOKUP_VX_INFO;
+}
+
+extern void vxh_dump_history(void);
+
+#else  /* CONFIG_VSERVER_HISTORY */
+
+#define	vxh_throw_oops()	do { } while (0)
+
+#define vxh_get_vx_info(v)	do { } while (0)
+#define vxh_put_vx_info(v)	do { } while (0)
+
+#define vxh_set_vx_info(v,d)	do { } while (0)
+#define vxh_clr_vx_info(v,d)	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_dump_history()	do { } while (0)
+
+
+#endif /* CONFIG_VSERVER_HISTORY */
 
 #endif /* _VX_DEBUG_H */
diff -u linux-2.6.9-vs1.9.3-w03/kernel/vserver/context.c linux-2.6.9-vs1.9.3-w03/kernel/vserver/context.c
--- linux-2.6.9-vs1.9.3-w03/kernel/vserver/context.c	2005-01-13 13:19:35.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/kernel/vserver/context.c	2005-01-13 13:19:35.000000000 +0100
@@ -80,6 +80,7 @@
 
 	vxdprintk(VXD_CBIT(xid, 0),
 		"alloc_vx_info(%d) = %p", xid, new);
+	vxh_alloc_vx_info(new);
 	return new;
 }
 
@@ -91,6 +92,7 @@
 {
 	vxdprintk(VXD_CBIT(xid, 0),
 		"dealloc_vx_info(%p)", vxi);
+	vxh_dealloc_vx_info(vxi);
 
 	vxi->vx_hlist.next = LIST_POISON1;
 	vxi->vx_id = -1;
@@ -199,6 +201,8 @@
 
 	vxdprintk(VXD_CBIT(xid, 4),
 		"__hash_vx_info: %p[#%d]", vxi, vxi->vx_id);
+	vxh_hash_vx_info(vxi);
+
 	get_vx_info(vxi);
 	vxi->vx_state |= VXS_HASHED;
 	head = &vx_info_hash[__hashval(vxi->vx_id)];
@@ -214,6 +218,8 @@
 {
 	vxdprintk(VXD_CBIT(xid, 4),
 		"__unhash_vx_info: %p[#%d]", vxi, vxi->vx_id);
+	vxh_unhash_vx_info(vxi);
+
 	vxi->vx_state &= ~VXS_HASHED;
 	hlist_del_rcu(&vxi->vx_hlist);
 
@@ -244,6 +250,7 @@
 	vxdprintk(VXD_CBIT(xid, 0),
 		"__lookup_vx_info(#%u): %p[#%u]",
 		xid, vxi, vxi?vxi->vx_id:0);
+	vxh_lookup_vx_info(xid, vxi);
 	return vxi;
 }
 
@@ -328,6 +335,7 @@
 out_unlock:
 	spin_unlock(&vx_info_hash_lock);
 	rcu_read_unlock();
+	vxh_loc_vx_info(id, vxi);
 	if (new)
 		__dealloc_vx_info(new);
 	return vxi;
only in patch2:
unchanged:
--- linux-2.6.9-vs1.9.3-w02/arch/i386/kernel/traps.c	2005-01-13 13:19:12.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/arch/i386/kernel/traps.c	2005-01-13 13:19:35.000000000 +0100
@@ -322,6 +322,7 @@ void die(const char * str, struct pt_reg
 	};
 	static int die_counter;
 
+	vxh_throw_oops();
 	if (die.lock_owner != smp_processor_id()) {
 		console_verbose();
 		spin_lock_irq(&die.lock);
@@ -356,6 +357,7 @@ void die(const char * str, struct pt_reg
 	bust_spinlocks(0);
 	die.lock_owner = -1;
 	spin_unlock_irq(&die.lock);
+	vxh_dump_history();
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
only in patch2:
unchanged:
--- linux-2.6.9-vs1.9.3-w02/include/linux/vserver/debug_cmd.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/include/linux/vserver/debug_cmd.h	2005-01-13 13:19:35.000000000 +0100
@@ -0,0 +1,14 @@
+#ifndef _VX_DEBUG_CMD_H
+#define _VX_DEBUG_CMD_H
+
+
+/* debug commands */
+
+#define VCMD_dump_history	VC_CMD(DEBUG, 1, 0)
+
+#ifdef	__KERNEL__
+
+extern int vc_dump_history(uint32_t);
+
+#endif	/* __KERNEL__ */
+#endif	/* _VX_DEBUG_CMD_H */
only in patch2:
unchanged:
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/history.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/kernel/vserver/history.c	2005-01-13 13:19:35.000000000 +0100
@@ -0,0 +1,167 @@
+/*
+ *  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
+ *
+ */
+
+#include <linux/config.h>
+#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>
+
+
+#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);
+
+
+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;
+}
+
+
+#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.refcnt: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_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_SET_VX_INFO)?"set":"clr",
+			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:
+		printk( VXH_LOC_FMTS " __%s_vx_info [#%d] -> " VXH_VXI_FMTS "\n",
+			VXH_LOC_ARGS(e),
+			(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,j;
+
+	printk("History:\tSEQ: %8x\tNR_CPUS: %d\n",
+		atomic_read(&sequence), NR_CPUS);
+
+	for (i=0; i < VXH_SIZE; i++) {
+		for (j=0; j < NR_CPUS; j++) {
+			struct _vx_history *hist =
+				&per_cpu(vx_history_buffer, j);
+			unsigned int index = (hist->counter-i) % VXH_SIZE;
+			struct _vx_hist_entry *entry = &hist->entry[index];
+
+			vxh_dump_entry(entry, j);
+		}
+	}
+}
+
+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;
+}
+
+EXPORT_SYMBOL_GPL(vxh_advance);
+
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/Kconfig linux-2.6.9-vs1.9.3-w03/kernel/vserver/Kconfig
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/Kconfig	2005-01-13 12:40:42.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/kernel/vserver/Kconfig	2005-01-13 13:19:35.000000000 +0100
@@ -92,5 +92,23 @@ config	VSERVER_DEBUG
 	  overhead (~ ??%) to all vserver related functions and
 	  increases the kernel size by about 20k.
 
+config	VSERVER_HISTORY
+	bool	"Compile History Tracing"
+	depends on VSERVER_DEBUG
+	default n
+	help
+	  Set this to yes if you want to record the history of
+	  linux-vserver activities, so they can be replayed on
+	  a kernel panic (oops)
+
+config	VSERVER_HISTORY_SIZE
+	int "Per CPU History Size (32-65536)"
+	depends on VSERVER_HISTORY
+	range 32 65536
+	default 64
+	help
+	  This allows you to specify the number of entries in
+	  the per CPU history buffer.
+
 endmenu
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/Makefile linux-2.6.9-vs1.9.3-w03/kernel/vserver/Makefile
--- linux-2.6.9-vs1.9.3-w02/kernel/vserver/Makefile	2005-01-13 12:40:42.000000000 +0100
+++ linux-2.6.9-vs1.9.3-w03/kernel/vserver/Makefile	2005-01-13 13:19:35.000000000 +0100
@@ -10,4 +10,5 @@ vserver-y	:= switch.o context.o namespac
 
 vserver-$(CONFIG_VSERVER_DEBUG) += sysctl.o
 vserver-$(CONFIG_VSERVER_LEGACY) += legacy.o
+vserver-$(CONFIG_VSERVER_HISTORY) += history.o
 
diff -NurpP --minimal linux-2.6.9-vs1.9.3-w02/kernel/vserver/switch.c linux-2.6.9-vs1.9.3-w03/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/kernel/vserver/switch.c	2005-01-13 13:19:35.000000000 +0100
@@ -64,6 +64,13 @@ vc_get_version(uint32_t id)
 	case VCMD_get_version:
 		return vc_get_version(id);
 
+	case VCMD_dump_history:
+#ifdef	CONFIG_VSERVER_HISTORY
+		return vc_dump_history(id);
+#else
+		return -ENOSYS;
+#endif
+
 #ifdef	CONFIG_VSERVER_LEGACY
 	case VCMD_new_s_context:
 		return vc_new_s_context(id, data);
