]> git.proxmox.com Git - mirror_spl-debian.git/blame - include/sys/debug.h
Minor improvement to taskq handling. This is a small step towards
[mirror_spl-debian.git] / include / sys / debug.h
CommitLineData
f4b37741 1#ifndef _SPL_DEBUG_H
2#define _SPL_DEBUG_H
3
57d1b188 4#include <linux/sched.h> /* THREAD_SIZE */
5#include <linux/proc_fs.h>
6
8d0f1ee9 7extern unsigned long spl_debug_mask;
8extern unsigned long spl_debug_subsys;
9
57d1b188 10#define S_UNDEFINED 0x00000001
11#define S_ATOMIC 0x00000002
12#define S_KOBJ 0x00000004
13#define S_VNODE 0x00000008
14#define S_TIME 0x00000010
15#define S_RWLOCK 0x00000020
16#define S_THREAD 0x00000040
17#define S_CONDVAR 0x00000080
18#define S_MUTEX 0x00000100
19#define S_RNG 0x00000200
20#define S_TASKQ 0x00000400
21#define S_KMEM 0x00000800
22#define S_DEBUG 0x00001000
23#define S_GENERIC 0x00002000
24#define S_PROC 0x00004000
937879f1 25#define S_MODULE 0x00008000
57d1b188 26
27#define D_TRACE 0x00000001
28#define D_INFO 0x00000002
29#define D_WARNING 0x00000004
30#define D_ERROR 0x00000008
31#define D_EMERG 0x00000010
32#define D_CONSOLE 0x00000020
33#define D_IOCTL 0x00000040
34#define D_DPRINTF 0x00000080
35#define D_OTHER 0x00000100
36
37#define D_CANTMASK (D_ERROR | D_EMERG | D_WARNING | D_CONSOLE)
38#define DEBUG_SUBSYSTEM S_UNDEFINED
39
40int debug_init(void);
41void debug_fini(void);
42int spl_debug_mask2str(char *str, int size, unsigned long mask, int is_subsys);
43int spl_debug_str2mask(unsigned long *mask, const char *str, int is_subsys);
44
45extern unsigned long spl_debug_subsys;
46extern unsigned long spl_debug_mask;
47extern unsigned long spl_debug_printk;
48extern int spl_debug_mb;
49extern unsigned int spl_debug_binary;
50extern unsigned int spl_debug_catastrophe;
51extern unsigned int spl_debug_panic_on_bug;
52extern char spl_debug_file_path[PATH_MAX];
53extern unsigned int spl_console_ratelimit;
54extern long spl_console_max_delay;
55extern long spl_console_min_delay;
56extern unsigned int spl_console_backoff;
57extern unsigned int spl_debug_stack;
58
b831734a 59#define TCD_MAX_PAGES (5 << (20 - PAGE_SHIFT))
60#define TCD_STOCK_PAGES (TCD_MAX_PAGES)
61#define TRACE_CONSOLE_BUFFER_SIZE 1024
57d1b188 62
b831734a 63#define SPL_DEFAULT_MAX_DELAY (600 * HZ)
64#define SPL_DEFAULT_MIN_DELAY ((HZ + 1) / 2)
65#define SPL_DEFAULT_BACKOFF 2
57d1b188 66
7fea96c0 67#define DL_NOTHREAD 0x0001 /* Do not create a new thread */
b831734a 68#define DL_SINGLE_CPU 0x0002 /* Collect pages from this CPU */
7fea96c0 69
70typedef struct dumplog_priv {
71 wait_queue_head_t dp_waitq;
72 pid_t dp_pid;
73 int dp_flags;
74 atomic_t dp_done;
75} dumplog_priv_t;
76
57d1b188 77typedef struct {
78 unsigned long cdls_next;
79 int cdls_count;
80 long cdls_delay;
81} spl_debug_limit_state_t;
82
83/* Three trace data types */
84typedef enum {
85 TCD_TYPE_PROC,
86 TCD_TYPE_SOFTIRQ,
87 TCD_TYPE_IRQ,
88 TCD_TYPE_MAX
89} tcd_type_t;
90
91union trace_data_union {
92 struct trace_cpu_data {
93 /* pages with trace records not yet processed by tracefiled */
94 struct list_head tcd_pages;
95 /* number of pages on ->tcd_pages */
96 unsigned long tcd_cur_pages;
97 /* Max number of pages allowed on ->tcd_pages */
98 unsigned long tcd_max_pages;
99
100 /*
101 * preallocated pages to write trace records into. Pages from
102 * ->tcd_stock_pages are moved to ->tcd_pages by spl_debug_msg().
103 *
104 * This list is necessary, because on some platforms it's
105 * impossible to perform efficient atomic page allocation in a
106 * non-blockable context.
107 *
108 * Such platforms fill ->tcd_stock_pages "on occasion", when
109 * tracing code is entered in blockable context.
110 *
111 * trace_get_tage_try() tries to get a page from
112 * ->tcd_stock_pages first and resorts to atomic page
113 * allocation only if this queue is empty. ->tcd_stock_pages
114 * is replenished when tracing code is entered in blocking
115 * context (darwin-tracefile.c:trace_get_tcd()). We try to
116 * maintain TCD_STOCK_PAGES (40 by default) pages in this
117 * queue. Atomic allocation is only required if more than
118 * TCD_STOCK_PAGES pagesful are consumed by trace records all
119 * emitted in non-blocking contexts. Which is quite unlikely.
120 */
121 struct list_head tcd_stock_pages;
122 /* number of pages on ->tcd_stock_pages */
123 unsigned long tcd_cur_stock_pages;
124
125 unsigned short tcd_shutting_down;
126 unsigned short tcd_cpu;
127 unsigned short tcd_type;
128 /* The factors to share debug memory. */
129 unsigned short tcd_pages_factor;
130 } tcd;
131 char __pad[L1_CACHE_ALIGN(sizeof(struct trace_cpu_data))];
132};
133
134extern union trace_data_union (*trace_data[TCD_TYPE_MAX])[NR_CPUS];
135
136#define tcd_for_each(tcd, i, j) \
137 for (i = 0; trace_data[i] != NULL; i++) \
138 for (j = 0, ((tcd) = &(*trace_data[i])[j].tcd); \
139 j < num_possible_cpus(); j++, (tcd) = &(*trace_data[i])[j].tcd)
140
141#define tcd_for_each_type_lock(tcd, i) \
142 for (i = 0; trace_data[i] && \
143 (tcd = &(*trace_data[i])[smp_processor_id()].tcd) && \
144 trace_lock_tcd(tcd); trace_unlock_tcd(tcd), i++)
145
146struct trace_page {
147 struct page * page; /* page itself */
148 struct list_head linkage; /* Used by lists in trace_data_union */
149 unsigned int used; /* number of bytes used within this page */
150 unsigned short cpu; /* cpu that owns this page */
151 unsigned short type; /* type(context) of this page */
152};
153
154struct page_collection {
155 struct list_head pc_pages;
156 spinlock_t pc_lock;
157 int pc_want_daemon_pages;
158};
159
b831734a 160#define SBUG() spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0);
2fae1b3d 161
937879f1 162#ifdef __ia64__
163#define CDEBUG_STACK() (THREAD_SIZE - \
164 ((unsigned long)__builtin_dwarf_cfa() & \
165 (THREAD_SIZE - 1)))
166#else
167#define CDEBUG_STACK() (THREAD_SIZE - \
168 ((unsigned long)__builtin_frame_address(0) & \
169 (THREAD_SIZE - 1)))
170# endif /* __ia64__ */
171
b831734a 172/* DL_SINGLE_CPU flag is passed to spl_debug_bug() because we are about
173 * to over run our stack and likely damage at least one other unknown
174 * thread stack. We must finish generating the needed debug info within
175 * this thread context because once we yeild the CPU its very likely
176 * the system will crash.
7fea96c0 177 */
937879f1 178#define __CHECK_STACK(file, func, line) \
179do { \
b831734a 180 if (unlikely(CDEBUG_STACK() > spl_debug_stack)) { \
181 spl_debug_stack = CDEBUG_STACK(); \
937879f1 182 \
b831734a 183 if (unlikely(CDEBUG_STACK() > (4 * THREAD_SIZE) / 5)) { \
184 spl_debug_msg(NULL, D_TRACE, D_WARNING, \
185 file, func, line, "Error " \
186 "exceeded maximum safe stack " \
187 "size (%lu/%lu)\n", \
188 CDEBUG_STACK(), THREAD_SIZE); \
189 spl_debug_bug(file, func, line, DL_SINGLE_CPU); \
190 } \
937879f1 191 } \
192} while (0)
193
892d5106 194#define CHECK_STACK() __CHECK_STACK(__FILE__, __func__, __LINE__)
937879f1 195
57d1b188 196/* ASSERTION that is safe to use within the debug system */
b831734a 197#define __ASSERT(cond) \
198do { \
199 if (unlikely(!(cond))) { \
200 printk(KERN_ERR "ASSERTION(" #cond ") failed"); \
6e605b6e 201 BUG(); \
b831734a 202 } \
57d1b188 203} while (0)
204
b831734a 205#define __ASSERT_TAGE_INVARIANT(tage) \
206do { \
207 __ASSERT(tage != NULL); \
208 __ASSERT(tage->page != NULL); \
209 __ASSERT(tage->used <= PAGE_SIZE); \
210 __ASSERT(page_count(tage->page) > 0); \
57d1b188 211} while(0)
212
213/* ASSERTION that will debug log used outside the debug sysytem */
214#define ASSERT(cond) \
215do { \
b831734a 216 CHECK_STACK(); \
217 \
57d1b188 218 if (unlikely(!(cond))) { \
219 spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
220 __FILE__, __FUNCTION__, __LINE__, \
221 "ASSERTION(" #cond ") failed\n"); \
b831734a 222 SBUG(); \
223 } \
57d1b188 224} while (0)
225
226#define ASSERTF(cond, fmt, a...) \
227do { \
b831734a 228 CHECK_STACK(); \
229 \
57d1b188 230 if (unlikely(!(cond))) { \
231 spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
232 __FILE__, __FUNCTION__, __LINE__, \
233 "ASSERTION(" #cond ") failed:" fmt, \
234 ## a); \
b831734a 235 SBUG(); \
57d1b188 236 } \
237} while (0)
238
239#define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST) \
240do { \
b831734a 241 CHECK_STACK(); \
242 \
243 if (!((TYPE)(LEFT) OP (TYPE)(RIGHT))) { \
57d1b188 244 spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
245 __FILE__, __FUNCTION__, __LINE__, \
246 "VERIFY3(" FMT " " #OP " " FMT ")\n", \
b831734a 247 CAST (LEFT), CAST (RIGHT)); \
248 SBUG(); \
57d1b188 249 } \
250} while (0)
251
252#define VERIFY3S(x,y,z) VERIFY3_IMPL(x, y, z, int64_t, "%ld", (long))
253#define VERIFY3U(x,y,z) VERIFY3_IMPL(x, y, z, uint64_t, "%lu", (unsigned long))
254#define VERIFY3P(x,y,z) VERIFY3_IMPL(x, y, z, uintptr_t, "%p", (void *))
255
256#define ASSERT3S(x,y,z) VERIFY3S(x, y, z)
257#define ASSERT3U(x,y,z) VERIFY3U(x, y, z)
258#define ASSERT3P(x,y,z) VERIFY3P(x, y, z)
259
b831734a 260#define VERIFY(x) ASSERT(x)
57d1b188 261
262#define spl_debug_msg(cdls, subsys, mask, file, fn, line, format, a...) \
263 spl_debug_vmsg(cdls, subsys, mask, file, fn, \
264 line, NULL, NULL, format, ##a)
265
57d1b188 266#define __CDEBUG(cdls, subsys, mask, format, a...) \
267do { \
268 CHECK_STACK(); \
269 \
270 if (((mask) & D_CANTMASK) != 0 || \
271 ((spl_debug_mask & (mask)) != 0 && \
272 (spl_debug_subsys & (subsys)) != 0)) \
273 spl_debug_msg(cdls, subsys, mask, \
274 __FILE__, __FUNCTION__, __LINE__, \
275 format, ## a); \
276} while (0)
277
278#define CDEBUG(mask, format, a...) \
279 __CDEBUG(NULL, DEBUG_SUBSYSTEM, mask, format, ## a)
280
281#define __CDEBUG_LIMIT(subsys, mask, format, a...) \
282do { \
283 static spl_debug_limit_state_t cdls; \
284 \
285 __CDEBUG(&cdls, subsys, mask, format, ## a); \
286} while (0)
287
288#define CDEBUG_LIMIT(mask, format, a...) \
289 __CDEBUG_LIMIT(DEBUG_SUBSYSTEM, mask, format, ## a)
290
57d1b188 291#define CWARN(fmt, a...) CDEBUG_LIMIT(D_WARNING, fmt, ## a)
292#define CERROR(fmt, a...) CDEBUG_LIMIT(D_ERROR, fmt, ## a)
293#define CEMERG(fmt, a...) CDEBUG_LIMIT(D_EMERG, fmt, ## a)
294#define CONSOLE(mask, fmt, a...) CDEBUG(D_CONSOLE | (mask), fmt, ## a)
295
296#define GOTO(label, rc) \
297do { \
298 long GOTO__ret = (long)(rc); \
299 CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \
300 #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\
301 (signed long)GOTO__ret); \
302 goto label; \
303} while (0)
304
305#define RETURN(rc) \
306do { \
307 typeof(rc) RETURN__ret = (rc); \
308 CDEBUG(D_TRACE, "Process leaving (rc=%lu : %ld : %lx)\n", \
309 (long)RETURN__ret, (long)RETURN__ret, (long)RETURN__ret);\
310 return RETURN__ret; \
311} while (0)
312
313#define ENTRY \
314do { \
315 CDEBUG(D_TRACE, "Process entered\n"); \
316} while (0)
317
318#define EXIT \
319do { \
320 CDEBUG(D_TRACE, "Process leaving\n"); \
321} while(0)
322
323extern int spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask,
b831734a 324 const char *file, const char *fn, const int line,
325 const char *format1, va_list args, const char *format2, ...);
57d1b188 326
327extern unsigned long spl_debug_set_mask(unsigned long mask);
328extern unsigned long spl_debug_get_mask(void);
329extern unsigned long spl_debug_set_subsys(unsigned long mask);
330extern unsigned long spl_debug_get_subsys(void);
331extern int spl_debug_set_mb(int mb);
332extern int spl_debug_get_mb(void);
333
7fea96c0 334extern int spl_debug_dumplog(int flags);
57d1b188 335extern void spl_debug_dumpstack(struct task_struct *tsk);
7fea96c0 336extern void spl_debug_bug(char *file, const char *func, const int line, int flags);
57d1b188 337
338extern int spl_debug_clear_buffer(void);
339extern int spl_debug_mark_buffer(char *text);
8d0f1ee9 340
f4b37741 341#endif /* SPL_DEBUG_H */