1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
4 /* Debugging facilities. */
7 * This file contains generic debugging functions used by reiser4. Roughly
10 * panicking: reiser4_do_panic(), reiser4_print_prefix().
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().
32 #include <linux/sysfs.h>
33 #include <linux/slab.h>
34 #include <linux/types.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>
45 static void reiser4_report_err(void);
47 #define reiser4_report_err() noop
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;
69 * check for recursive panic.
74 spin_lock(&panic_guard
);
75 va_start(args
, format
);
76 vsnprintf(panic_buf
, sizeof(panic_buf
), format
, 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
96 /* to make gcc happy about noreturn attribute */
97 panic("%s", panic_buf
);
102 reiser4_print_prefix(const char *level
, int reperr
, const char *mid
,
103 const char *function
, const char *file
, int lineno
)
108 if (unlikely(in_interrupt() || in_irq())) {
112 comm
= current
->comm
;
115 printk("%sreiser4[%.16s(%i)]: %s (%s:%i)[%s]:\n",
116 level
, comm
, pid
, function
, file
, lineno
, mid
);
118 reiser4_report_err();
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());
128 return signal_pending(current
);
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
);
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"
152 "txnh: %i, atom: %i, stack: %i, txnmgr: %i, "
153 "ktxnmgrd: %i, fq: %i\n"
155 "cbk_cache: %i (r:%i,w%i), "
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
,
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());
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();
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
225 int reiser4_commit_check_locks(void)
227 reiser4_lock_cnt_info
*counters
;
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
;
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();
258 ctx
->err
.code
= code
;
259 ctx
->err
.file
= file
;
260 ctx
->err
.line
= line
;
267 * report error information recorder by reiser4_return_err().
269 static void reiser4_report_err(void)
271 reiser4_context
*ctx
= get_current_context_check();
274 if (ctx
->err
.code
!= 0) {
275 printk("code: %i at %s:%i\n",
276 ctx
->err
.code
, ctx
->err
.file
, ctx
->err
.line
);
282 #endif /* REISER4_DEBUG */
287 * this functions just drops into kernel debugger. It is a convenient place to
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);
302 c-indentation-style: "K&R"