Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / kernel / vserver / history.c
1 /*
2  *  kernel/vserver/history.c
3  *
4  *  Virtual Context History Backtrace
5  *
6  *  Copyright (C) 2004-2005  Herbert Pƶtzl
7  *
8  *  V0.01  basic structure
9  *  V0.02  hash/unhash and trace
10  *  V0.03  preemption fixes
11  *
12  */
13
14 #include <linux/errno.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/ctype.h>
18
19 #include <asm/uaccess.h>
20 #include <asm/atomic.h>
21 #include <asm/unistd.h>
22
23 #include <linux/vserver/debug.h>
24
25
26 #ifdef  CONFIG_VSERVER_HISTORY
27 #define VXH_SIZE        CONFIG_VSERVER_HISTORY_SIZE
28 #else
29 #define VXH_SIZE        64
30 #endif
31
32 struct _vx_history {
33         unsigned int counter;
34
35         struct _vx_hist_entry entry[VXH_SIZE+1];
36 };
37
38
39 DEFINE_PER_CPU(struct _vx_history, vx_history_buffer);
40
41 unsigned volatile int vxh_active = 1;
42
43 static atomic_t sequence = ATOMIC_INIT(0);
44
45
46 /*      vxh_advance()
47
48         * requires disabled preemption                          */
49
50 struct _vx_hist_entry *vxh_advance(void *loc)
51 {
52         unsigned int cpu = smp_processor_id();
53         struct _vx_history *hist = &per_cpu(vx_history_buffer, cpu);
54         struct _vx_hist_entry *entry;
55         unsigned int index;
56
57         index = vxh_active ? (hist->counter++ % VXH_SIZE) : VXH_SIZE;
58         entry = &hist->entry[index];
59
60         entry->seq = atomic_inc_return(&sequence);
61         entry->loc = loc;
62         return entry;
63 }
64
65
66 #define VXH_LOC_FMTS    "(#%04x,*%d):%p"
67
68 #define VXH_LOC_ARGS(e) (e)->seq, cpu, (e)->loc
69
70
71 #define VXH_VXI_FMTS    "%p[#%d,%d.%d]"
72
73 #define VXH_VXI_ARGS(e) (e)->vxi.ptr,                   \
74                         (e)->vxi.ptr?(e)->vxi.xid:0,    \
75                         (e)->vxi.ptr?(e)->vxi.usecnt:0, \
76                         (e)->vxi.ptr?(e)->vxi.tasks:0
77
78 void    vxh_dump_entry(struct _vx_hist_entry *e, unsigned cpu)
79 {
80         switch (e->type) {
81         case VXH_THROW_OOPS:
82                 printk( VXH_LOC_FMTS " oops \n", VXH_LOC_ARGS(e));
83                 break;
84
85         case VXH_GET_VX_INFO:
86         case VXH_PUT_VX_INFO:
87                 printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS "\n",
88                         VXH_LOC_ARGS(e),
89                         (e->type==VXH_GET_VX_INFO)?"get":"put",
90                         VXH_VXI_ARGS(e));
91                 break;
92
93         case VXH_INIT_VX_INFO:
94         case VXH_SET_VX_INFO:
95         case VXH_CLR_VX_INFO:
96                 printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS " @%p\n",
97                         VXH_LOC_ARGS(e),
98                         (e->type==VXH_INIT_VX_INFO)?"init":
99                         ((e->type==VXH_SET_VX_INFO)?"set":"clr"),
100                         VXH_VXI_ARGS(e), e->sc.data);
101                 break;
102
103         case VXH_CLAIM_VX_INFO:
104         case VXH_RELEASE_VX_INFO:
105                 printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS " @%p\n",
106                         VXH_LOC_ARGS(e),
107                         (e->type==VXH_CLAIM_VX_INFO)?"claim":"release",
108                         VXH_VXI_ARGS(e), e->sc.data);
109                 break;
110
111         case VXH_ALLOC_VX_INFO:
112         case VXH_DEALLOC_VX_INFO:
113                 printk( VXH_LOC_FMTS " %s_vx_info " VXH_VXI_FMTS "\n",
114                         VXH_LOC_ARGS(e),
115                         (e->type==VXH_ALLOC_VX_INFO)?"alloc":"dealloc",
116                         VXH_VXI_ARGS(e));
117                 break;
118
119         case VXH_HASH_VX_INFO:
120         case VXH_UNHASH_VX_INFO:
121                 printk( VXH_LOC_FMTS " __%s_vx_info " VXH_VXI_FMTS "\n",
122                         VXH_LOC_ARGS(e),
123                         (e->type==VXH_HASH_VX_INFO)?"hash":"unhash",
124                         VXH_VXI_ARGS(e));
125                 break;
126
127         case VXH_LOC_VX_INFO:
128         case VXH_LOOKUP_VX_INFO:
129         case VXH_CREATE_VX_INFO:
130                 printk( VXH_LOC_FMTS " __%s_vx_info [#%d] -> " VXH_VXI_FMTS "\n",
131                         VXH_LOC_ARGS(e),
132                         (e->type==VXH_CREATE_VX_INFO)?"create":
133                         ((e->type==VXH_LOC_VX_INFO)?"loc":"lookup"),
134                         e->ll.arg, VXH_VXI_ARGS(e));
135                 break;
136         }
137 }
138
139 static void __vxh_dump_history(void)
140 {
141         unsigned int i, cpu;
142
143         printk("History:\tSEQ: %8x\tNR_CPUS: %d\n",
144                 atomic_read(&sequence), NR_CPUS);
145
146         for (i=0; i < VXH_SIZE; i++) {
147                 for_each_online_cpu(cpu) {
148                         struct _vx_history *hist =
149                                 &per_cpu(vx_history_buffer, cpu);
150                         unsigned int index = (hist->counter-i) % VXH_SIZE;
151                         struct _vx_hist_entry *entry = &hist->entry[index];
152
153                         vxh_dump_entry(entry, cpu);
154                 }
155         }
156 }
157
158 void    vxh_dump_history(void)
159 {
160         vxh_active = 0;
161 #ifdef CONFIG_SMP
162         local_irq_enable();
163         smp_send_stop();
164         local_irq_disable();
165 #endif
166         __vxh_dump_history();
167 }
168
169
170 /* vserver syscall commands below here */
171
172
173 int     vc_dump_history(uint32_t id)
174 {
175         vxh_active = 0;
176         __vxh_dump_history();
177         vxh_active = 1;
178
179         return 0;
180 }
181
182 EXPORT_SYMBOL_GPL(vxh_advance);
183