mm-only debug patch...
[mmotm.git] / fs / reiser4 / debug.c
blobb5b56fa8b08add48f8fc783695e5a67c2af9f6ff
1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
2 * reiser4/README */
4 /* Debugging facilities. */
6 /*
7 * This file contains generic debugging functions used by reiser4. Roughly
8 * following:
10 * panicking: reiser4_do_panic(), reiser4_print_prefix().
12 * locking:
13 * reiser4_schedulable(), reiser4_lock_counters(), print_lock_counters(),
14 * reiser4_no_counters_are_held(), reiser4_commit_check_locks()
16 * error code monitoring (see comment before RETERR macro):
17 * reiser4_return_err(), reiser4_report_err().
19 * stack back-tracing: fill_backtrace()
21 * miscellaneous: reiser4_preempt_point(), call_on_each_assert(),
22 * reiser4_debugtrap().
26 #include "reiser4.h"
27 #include "context.h"
28 #include "super.h"
29 #include "txnmgr.h"
30 #include "znode.h"
32 #include <linux/sysfs.h>
33 #include <linux/slab.h>
34 #include <linux/types.h>
35 #include <linux/fs.h>
36 #include <linux/spinlock.h>
37 #include <linux/kallsyms.h>
38 #include <linux/vmalloc.h>
39 #include <linux/ctype.h>
40 #include <linux/sysctl.h>
41 #include <linux/hardirq.h>
43 #if 0
44 #if REISER4_DEBUG
45 static void reiser4_report_err(void);
46 #else
47 #define reiser4_report_err() noop
48 #endif
49 #endif /* 0 */
52 * global buffer where message given to reiser4_panic is formatted.
54 static char panic_buf[REISER4_PANIC_MSG_BUFFER_SIZE];
57 * lock protecting consistency of panic_buf under concurrent panics
59 static DEFINE_SPINLOCK(panic_guard);
61 /* Your best friend. Call it on each occasion. This is called by
62 fs/reiser4/debug.h:reiser4_panic(). */
63 void reiser4_do_panic(const char *format/* format string */ , ... /* rest */)
65 static int in_panic = 0;
66 va_list args;
69 * check for recursive panic.
71 if (in_panic == 0) {
72 in_panic = 1;
74 spin_lock(&panic_guard);
75 va_start(args, format);
76 vsnprintf(panic_buf, sizeof(panic_buf), format, args);
77 va_end(args);
78 printk(KERN_EMERG "reiser4 panicked cowardly: %s", panic_buf);
79 spin_unlock(&panic_guard);
82 * if kernel debugger is configured---drop in. Early dropping
83 * into kgdb is not always convenient, because panic message
84 * is not yet printed most of the times. But:
86 * (1) message can be extracted from printk_buf[]
87 * (declared static inside of printk()), and
89 * (2) sometimes serial/kgdb combo dies while printing
90 * long panic message, so it's more prudent to break into
91 * debugger earlier.
94 DEBUGON(1);
96 /* to make gcc happy about noreturn attribute */
97 panic("%s", panic_buf);
100 #if 0
101 void
102 reiser4_print_prefix(const char *level, int reperr, const char *mid,
103 const char *function, const char *file, int lineno)
105 const char *comm;
106 int pid;
108 if (unlikely(in_interrupt() || in_irq())) {
109 comm = "interrupt";
110 pid = 0;
111 } else {
112 comm = current->comm;
113 pid = current->pid;
115 printk("%sreiser4[%.16s(%i)]: %s (%s:%i)[%s]:\n",
116 level, comm, pid, function, file, lineno, mid);
117 if (reperr)
118 reiser4_report_err();
120 #endif /* 0 */
122 /* Preemption point: this should be called periodically during long running
123 operations (carry, allocate, and squeeze are best examples) */
124 int reiser4_preempt_point(void)
126 assert("nikita-3008", reiser4_schedulable());
127 cond_resched();
128 return signal_pending(current);
131 #if REISER4_DEBUG
132 /* Debugging aid: return struct where information about locks taken by current
133 thread is accumulated. This can be used to formulate lock ordering
134 constraints and various assertions.
137 reiser4_lock_cnt_info *reiser4_lock_counters(void)
139 reiser4_context *ctx = get_current_context();
140 assert("jmacd-1123", ctx != NULL);
141 return &ctx->locks;
145 * print human readable information about locks held by the reiser4 context.
147 static void print_lock_counters(const char *prefix,
148 const reiser4_lock_cnt_info * info)
150 printk("%s: jnode: %i, tree: %i (r:%i,w:%i), dk: %i (r:%i,w:%i)\n"
151 "jload: %i, "
152 "txnh: %i, atom: %i, stack: %i, txnmgr: %i, "
153 "ktxnmgrd: %i, fq: %i\n"
154 "inode: %i, "
155 "cbk_cache: %i (r:%i,w%i), "
156 "eflush: %i, "
157 "zlock: %i,\n"
158 "spin: %i, long: %i inode_sem: (r:%i,w:%i)\n"
159 "d: %i, x: %i, t: %i\n", prefix,
160 info->spin_locked_jnode,
161 info->rw_locked_tree, info->read_locked_tree,
162 info->write_locked_tree,
163 info->rw_locked_dk, info->read_locked_dk, info->write_locked_dk,
164 info->spin_locked_jload,
165 info->spin_locked_txnh,
166 info->spin_locked_atom, info->spin_locked_stack,
167 info->spin_locked_txnmgr, info->spin_locked_ktxnmgrd,
168 info->spin_locked_fq,
169 info->spin_locked_inode,
170 info->rw_locked_cbk_cache,
171 info->read_locked_cbk_cache,
172 info->write_locked_cbk_cache,
173 info->spin_locked_super_eflush,
174 info->spin_locked_zlock,
175 info->spin_locked,
176 info->long_term_locked_znode,
177 info->inode_sem_r, info->inode_sem_w,
178 info->d_refs, info->x_refs, info->t_refs);
181 /* check that no spinlocks are held */
182 int reiser4_schedulable(void)
184 if (get_current_context_check() != NULL) {
185 if (!LOCK_CNT_NIL(spin_locked)) {
186 print_lock_counters("in atomic", reiser4_lock_counters());
187 return 0;
190 might_sleep();
191 return 1;
194 * return true, iff no locks are held.
196 int reiser4_no_counters_are_held(void)
198 reiser4_lock_cnt_info *counters;
200 counters = reiser4_lock_counters();
201 return
202 (counters->spin_locked_zlock == 0) &&
203 (counters->spin_locked_jnode == 0) &&
204 (counters->rw_locked_tree == 0) &&
205 (counters->read_locked_tree == 0) &&
206 (counters->write_locked_tree == 0) &&
207 (counters->rw_locked_dk == 0) &&
208 (counters->read_locked_dk == 0) &&
209 (counters->write_locked_dk == 0) &&
210 (counters->spin_locked_txnh == 0) &&
211 (counters->spin_locked_atom == 0) &&
212 (counters->spin_locked_stack == 0) &&
213 (counters->spin_locked_txnmgr == 0) &&
214 (counters->spin_locked_inode == 0) &&
215 (counters->spin_locked == 0) &&
216 (counters->long_term_locked_znode == 0) &&
217 (counters->inode_sem_r == 0) &&
218 (counters->inode_sem_w == 0) && (counters->d_refs == 0);
222 * return true, iff transaction commit can be done under locks held by the
223 * current thread.
225 int reiser4_commit_check_locks(void)
227 reiser4_lock_cnt_info *counters;
228 int inode_sem_r;
229 int inode_sem_w;
230 int result;
233 * inode's read/write semaphore is the only reiser4 lock that can be
234 * held during commit.
237 counters = reiser4_lock_counters();
238 inode_sem_r = counters->inode_sem_r;
239 inode_sem_w = counters->inode_sem_w;
241 counters->inode_sem_r = counters->inode_sem_w = 0;
242 result = reiser4_no_counters_are_held();
243 counters->inode_sem_r = inode_sem_r;
244 counters->inode_sem_w = inode_sem_w;
245 return result;
249 * fill "error site" in the current reiser4 context. See comment before RETERR
250 * macro for more details.
252 void reiser4_return_err(int code, const char *file, int line)
254 if (code < 0 && is_in_reiser4_context()) {
255 reiser4_context *ctx = get_current_context();
257 if (ctx != NULL) {
258 ctx->err.code = code;
259 ctx->err.file = file;
260 ctx->err.line = line;
265 #if 0
267 * report error information recorder by reiser4_return_err().
269 static void reiser4_report_err(void)
271 reiser4_context *ctx = get_current_context_check();
273 if (ctx != NULL) {
274 if (ctx->err.code != 0) {
275 printk("code: %i at %s:%i\n",
276 ctx->err.code, ctx->err.file, ctx->err.line);
280 #endif /* 0 */
282 #endif /* REISER4_DEBUG */
284 #if KERNEL_DEBUGGER
287 * this functions just drops into kernel debugger. It is a convenient place to
288 * put breakpoint in.
290 void reiser4_debugtrap(void)
292 /* do nothing. Put break point here. */
293 #if defined(CONFIG_KGDB) && !defined(CONFIG_REISER4_FS_MODULE)
294 extern void kgdb_breakpoint(void);
295 kgdb_breakpoint();
296 #endif
298 #endif
300 /* Make Linus happy.
301 Local variables:
302 c-indentation-style: "K&R"
303 mode-name: "LC"
304 c-basic-offset: 8
305 tab-width: 8
306 fill-column: 120
307 End: