]> git.proxmox.com Git - mirror_spl.git/blame - module/spl/spl-debug.c
Linux 2.6.35 compat: filp_fsync() dropped 'stuct dentry *'
[mirror_spl.git] / module / spl / spl-debug.c
CommitLineData
716154c5
BB
1/*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
715f6251 6 * UCRL-CODE-235197
57d1b188 7 *
716154c5
BB
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
10 *
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
57d1b188 15 *
716154c5 16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
715f6251 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
57d1b188 20 *
715f6251 21 * You should have received a copy of the GNU General Public License along
716154c5
BB
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting Layer (SPL) Debug Implementation.
25\*****************************************************************************/
57d1b188 26
27#include <linux/kmod.h>
28#include <linux/mm.h>
29#include <linux/vmalloc.h>
30#include <linux/pagemap.h>
31#include <linux/slab.h>
32#include <linux/ctype.h>
33#include <linux/kthread.h>
34#include <linux/hardirq.h>
35#include <linux/interrupt.h>
f6c81c5e 36#include <linux/spinlock.h>
ae4c36ad 37#include <linux/proc_compat.h>
f0ff89fc 38#include <linux/file_compat.h>
57d1b188 39#include <sys/sysmacros.h>
57d1b188 40#include <sys/debug.h>
41#include <spl-ctl.h>
57d1b188 42
43#ifdef DEBUG_SUBSYSTEM
44#undef DEBUG_SUBSYSTEM
45#endif
46
47#define DEBUG_SUBSYSTEM S_DEBUG
48
49unsigned long spl_debug_subsys = ~0;
50EXPORT_SYMBOL(spl_debug_subsys);
51module_param(spl_debug_subsys, long, 0644);
52MODULE_PARM_DESC(spl_debug_subsys, "Subsystem debugging level mask.");
53
54unsigned long spl_debug_mask = (D_EMERG | D_ERROR | D_WARNING | D_CONSOLE);
55EXPORT_SYMBOL(spl_debug_mask);
56module_param(spl_debug_mask, long, 0644);
57MODULE_PARM_DESC(spl_debug_mask, "Debugging level mask.");
58
59unsigned long spl_debug_printk = D_CANTMASK;
60EXPORT_SYMBOL(spl_debug_printk);
61module_param(spl_debug_printk, long, 0644);
62MODULE_PARM_DESC(spl_debug_printk, "Console printk level mask.");
63
64int spl_debug_mb = -1;
65EXPORT_SYMBOL(spl_debug_mb);
66module_param(spl_debug_mb, int, 0644);
67MODULE_PARM_DESC(spl_debug_mb, "Total debug buffer size.");
68
69unsigned int spl_debug_binary = 1;
70EXPORT_SYMBOL(spl_debug_binary);
71
72unsigned int spl_debug_catastrophe;
73EXPORT_SYMBOL(spl_debug_catastrophe);
74
3626ae6a 75unsigned int spl_debug_panic_on_bug = 0;
57d1b188 76EXPORT_SYMBOL(spl_debug_panic_on_bug);
77module_param(spl_debug_panic_on_bug, int, 0644);
78MODULE_PARM_DESC(spl_debug_panic_on_bug, "Panic on BUG");
79
80static char spl_debug_file_name[PATH_MAX];
627a7497 81char spl_debug_file_path[PATH_MAX] = "/tmp/spl-log";
57d1b188 82
83unsigned int spl_console_ratelimit = 1;
84EXPORT_SYMBOL(spl_console_ratelimit);
85
86long spl_console_max_delay;
87EXPORT_SYMBOL(spl_console_max_delay);
88
89long spl_console_min_delay;
90EXPORT_SYMBOL(spl_console_min_delay);
91
92unsigned int spl_console_backoff = SPL_DEFAULT_BACKOFF;
93EXPORT_SYMBOL(spl_console_backoff);
94
95unsigned int spl_debug_stack;
96EXPORT_SYMBOL(spl_debug_stack);
97
98static int spl_panic_in_progress;
99
100union trace_data_union (*trace_data[TCD_TYPE_MAX])[NR_CPUS] __cacheline_aligned;
101char *trace_console_buffers[NR_CPUS][3];
102struct rw_semaphore trace_sem;
103atomic_t trace_tage_allocated = ATOMIC_INIT(0);
104
7fea96c0 105static int spl_debug_dump_all_pages(dumplog_priv_t *dp, char *);
57d1b188 106static void trace_fini(void);
107
108
109/* Memory percentage breakdown by type */
110static unsigned int pages_factor[TCD_TYPE_MAX] = {
111 80, /* 80% pages for TCD_TYPE_PROC */
112 10, /* 10% pages for TCD_TYPE_SOFTIRQ */
113 10 /* 10% pages for TCD_TYPE_IRQ */
114};
115
57d1b188 116const char *
117spl_debug_subsys2str(int subsys)
118{
119 switch (subsys) {
120 default:
121 return NULL;
122 case S_UNDEFINED:
123 return "undefined";
124 case S_ATOMIC:
125 return "atomic";
126 case S_KOBJ:
127 return "kobj";
128 case S_VNODE:
129 return "vnode";
130 case S_TIME:
131 return "time";
132 case S_RWLOCK:
133 return "rwlock";
134 case S_THREAD:
135 return "thread";
136 case S_CONDVAR:
137 return "condvar";
138 case S_MUTEX:
139 return "mutex";
140 case S_RNG:
141 return "rng";
142 case S_TASKQ:
143 return "taskq";
144 case S_KMEM:
145 return "kmem";
e5bbd245 146 case S_DEBUG:
147 return "debug";
148 case S_GENERIC:
149 return "generic";
150 case S_PROC:
151 return "proc";
152 case S_MODULE:
153 return "module";
ec7d53e9
BB
154 case S_CRED:
155 return "cred";
57d1b188 156 }
157}
158
159const char *
160spl_debug_dbg2str(int debug)
161{
162 switch (debug) {
163 default:
164 return NULL;
165 case D_TRACE:
166 return "trace";
167 case D_INFO:
168 return "info";
169 case D_WARNING:
170 return "warning";
171 case D_ERROR:
172 return "error";
173 case D_EMERG:
174 return "emerg";
175 case D_CONSOLE:
176 return "console";
177 case D_IOCTL:
178 return "ioctl";
179 case D_DPRINTF:
180 return "dprintf";
181 case D_OTHER:
182 return "other";
183 }
184}
185
186int
187spl_debug_mask2str(char *str, int size, unsigned long mask, int is_subsys)
188{
189 const char *(*fn)(int bit) = is_subsys ? spl_debug_subsys2str :
190 spl_debug_dbg2str;
191 const char *token;
192 int i, bit, len = 0;
193
194 if (mask == 0) { /* "0" */
195 if (size > 0)
196 str[0] = '0';
197 len = 1;
198 } else { /* space-separated tokens */
199 for (i = 0; i < 32; i++) {
200 bit = 1 << i;
201
202 if ((mask & bit) == 0)
203 continue;
204
205 token = fn(bit);
206 if (token == NULL) /* unused bit */
207 continue;
208
209 if (len > 0) { /* separator? */
210 if (len < size)
211 str[len] = ' ';
212 len++;
213 }
214
215 while (*token != 0) {
216 if (len < size)
217 str[len] = *token;
218 token++;
219 len++;
220 }
221 }
222 }
223
224 /* terminate 'str' */
225 if (len < size)
226 str[len] = 0;
227 else
228 str[size - 1] = 0;
229
230 return len;
231}
232
233static int
234spl_debug_token2mask(int *mask, const char *str, int len, int is_subsys)
235{
236 const char *(*fn)(int bit) = is_subsys ? spl_debug_subsys2str :
237 spl_debug_dbg2str;
238 const char *token;
239 int i, j, bit;
240
241 /* match against known tokens */
242 for (i = 0; i < 32; i++) {
243 bit = 1 << i;
244
245 token = fn(bit);
246 if (token == NULL) /* unused? */
247 continue;
248
249 /* strcasecmp */
250 for (j = 0; ; j++) {
251 if (j == len) { /* end of token */
252 if (token[j] == 0) {
253 *mask = bit;
254 return 0;
255 }
256 break;
257 }
258
259 if (token[j] == 0)
260 break;
261
262 if (str[j] == token[j])
263 continue;
264
265 if (str[j] < 'A' || 'Z' < str[j])
266 break;
267
268 if (str[j] - 'A' + 'a' != token[j])
269 break;
270 }
271 }
272
273 return -EINVAL; /* no match */
274}
275
276int
277spl_debug_str2mask(unsigned long *mask, const char *str, int is_subsys)
278{
279 char op = 0;
280 int m = 0, matched, n, t;
281
282 /* Allow a number for backwards compatibility */
283 for (n = strlen(str); n > 0; n--)
284 if (!isspace(str[n-1]))
285 break;
286 matched = n;
287
288 if ((t = sscanf(str, "%i%n", &m, &matched)) >= 1 && matched == n) {
289 *mask = m;
290 return 0;
291 }
292
293 /* <str> must be a list of debug tokens or numbers separated by
294 * whitespace and optionally an operator ('+' or '-'). If an operator
295 * appears first in <str>, '*mask' is used as the starting point
296 * (relative), otherwise 0 is used (absolute). An operator applies to
297 * all following tokens up to the next operator. */
298 matched = 0;
299 while (*str != 0) {
300 while (isspace(*str)) /* skip whitespace */
301 str++;
302
303 if (*str == 0)
304 break;
305
306 if (*str == '+' || *str == '-') {
307 op = *str++;
308
309 /* op on first token == relative */
310 if (!matched)
311 m = *mask;
312
313 while (isspace(*str)) /* skip whitespace */
314 str++;
315
316 if (*str == 0) /* trailing op */
317 return -EINVAL;
318 }
319
320 /* find token length */
321 for (n = 0; str[n] != 0 && !isspace(str[n]); n++);
322
323 /* match token */
324 if (spl_debug_token2mask(&t, str, n, is_subsys) != 0)
325 return -EINVAL;
326
327 matched = 1;
328 if (op == '-')
329 m &= ~t;
330 else
331 m |= t;
332
333 str += n;
334 }
335
336 if (!matched)
337 return -EINVAL;
338
339 *mask = m;
340 return 0;
341}
342
57d1b188 343static void
344spl_debug_dumplog_internal(dumplog_priv_t *dp)
345{
346 void *journal_info;
347
348 journal_info = current->journal_info;
349 current->journal_info = NULL;
350
351 snprintf(spl_debug_file_name, sizeof(spl_debug_file_path) - 1,
352 "%s.%ld.%ld", spl_debug_file_path,
353 get_seconds(), (long)dp->dp_pid);
627a7497 354 printk("SPL: Dumping log to %s\n", spl_debug_file_name);
7fea96c0 355 spl_debug_dump_all_pages(dp, spl_debug_file_name);
57d1b188 356
357 current->journal_info = journal_info;
358}
359
360static int
361spl_debug_dumplog_thread(void *arg)
362{
363 dumplog_priv_t *dp = (dumplog_priv_t *)arg;
364
365 spl_debug_dumplog_internal(dp);
7fea96c0 366 atomic_set(&dp->dp_done, 1);
57d1b188 367 wake_up(&dp->dp_waitq);
3d061e9d 368 complete_and_exit(NULL, 0);
57d1b188 369
370 return 0; /* Unreachable */
371}
372
7fea96c0 373/* When flag is set do not use a new thread for the debug dump */
57d1b188 374int
7fea96c0 375spl_debug_dumplog(int flags)
57d1b188 376{
377 struct task_struct *tsk;
378 dumplog_priv_t dp;
57d1b188 379
7fea96c0 380 init_waitqueue_head(&dp.dp_waitq);
381 dp.dp_pid = current->pid;
382 dp.dp_flags = flags;
383 atomic_set(&dp.dp_done, 0);
57d1b188 384
7fea96c0 385 if (dp.dp_flags & DL_NOTHREAD) {
386 spl_debug_dumplog_internal(&dp);
387 } else {
57d1b188 388
7fea96c0 389 tsk = kthread_create(spl_debug_dumplog_thread,(void *)&dp,"spl_debug");
390 if (tsk == NULL)
391 return -ENOMEM;
392
393 wake_up_process(tsk);
394 wait_event(dp.dp_waitq, atomic_read(&dp.dp_done));
395 }
57d1b188 396
a8ac0b89 397 return 0;
57d1b188 398}
399EXPORT_SYMBOL(spl_debug_dumplog);
400
401static char *
402trace_get_console_buffer(void)
403{
404 int cpu = get_cpu();
405 int idx;
406
407 if (in_irq()) {
408 idx = 0;
409 } else if (in_softirq()) {
410 idx = 1;
411 } else {
412 idx = 2;
413 }
414
415 return trace_console_buffers[cpu][idx];
416}
417
418static void
419trace_put_console_buffer(char *buffer)
420{
421 put_cpu();
422}
423
f6c81c5e 424static int
425trace_lock_tcd(struct trace_cpu_data *tcd)
57d1b188 426{
f6c81c5e 427 __ASSERT(tcd->tcd_type < TCD_TYPE_MAX);
57d1b188 428
f6c81c5e 429 spin_lock_irqsave(&tcd->tcd_lock, tcd->tcd_lock_flags);
57d1b188 430
f6c81c5e 431 return 1;
57d1b188 432}
433
434static void
f6c81c5e 435trace_unlock_tcd(struct trace_cpu_data *tcd)
57d1b188 436{
f6c81c5e 437 __ASSERT(tcd->tcd_type < TCD_TYPE_MAX);
438
439 spin_unlock_irqrestore(&tcd->tcd_lock, tcd->tcd_lock_flags);
57d1b188 440}
441
f6c81c5e 442static struct trace_cpu_data *
443trace_get_tcd(void)
57d1b188 444{
f6c81c5e 445 int cpu;
446 struct trace_cpu_data *tcd;
447
448 cpu = get_cpu();
449 if (in_irq())
450 tcd = &(*trace_data[TCD_TYPE_IRQ])[cpu].tcd;
451 else if (in_softirq())
452 tcd = &(*trace_data[TCD_TYPE_SOFTIRQ])[cpu].tcd;
453 else
454 tcd = &(*trace_data[TCD_TYPE_PROC])[cpu].tcd;
57d1b188 455
f6c81c5e 456 trace_lock_tcd(tcd);
57d1b188 457
f6c81c5e 458 return tcd;
57d1b188 459}
460
461static void
f6c81c5e 462trace_put_tcd (struct trace_cpu_data *tcd)
57d1b188 463{
f6c81c5e 464 trace_unlock_tcd(tcd);
57d1b188 465
f6c81c5e 466 put_cpu();
57d1b188 467}
468
469static void
470trace_set_debug_header(struct spl_debug_header *header, int subsys,
471 int mask, const int line, unsigned long stack)
472{
473 struct timeval tv;
474
475 do_gettimeofday(&tv);
476
477 header->ph_subsys = subsys;
478 header->ph_mask = mask;
479 header->ph_cpu_id = smp_processor_id();
480 header->ph_sec = (__u32)tv.tv_sec;
481 header->ph_usec = tv.tv_usec;
482 header->ph_stack = stack;
483 header->ph_pid = current->pid;
484 header->ph_line_num = line;
485
486 return;
487}
488
489static void
490trace_print_to_console(struct spl_debug_header *hdr, int mask, const char *buf,
491 int len, const char *file, const char *fn)
492{
493 char *prefix = "SPL", *ptype = NULL;
494
495 if ((mask & D_EMERG) != 0) {
496 prefix = "SPLError";
497 ptype = KERN_EMERG;
498 } else if ((mask & D_ERROR) != 0) {
499 prefix = "SPLError";
500 ptype = KERN_ERR;
501 } else if ((mask & D_WARNING) != 0) {
502 prefix = "SPL";
503 ptype = KERN_WARNING;
504 } else if ((mask & (D_CONSOLE | spl_debug_printk)) != 0) {
505 prefix = "SPL";
506 ptype = KERN_INFO;
507 }
508
509 if ((mask & D_CONSOLE) != 0) {
510 printk("%s%s: %.*s", ptype, prefix, len, buf);
511 } else {
892d5106 512 printk("%s%s: %d:%d:(%s:%d:%s()) %.*s", ptype, prefix,
513 hdr->ph_pid, hdr->ph_stack, file,
514 hdr->ph_line_num, fn, len, buf);
57d1b188 515 }
516
517 return;
518}
519
520static int
521trace_max_debug_mb(void)
522{
523 return MAX(512, ((num_physpages >> (20 - PAGE_SHIFT)) * 80) / 100);
524}
525
57d1b188 526static struct trace_page *
527tage_alloc(int gfp)
528{
529 struct page *page;
530 struct trace_page *tage;
531
532 page = alloc_pages(gfp | __GFP_NOWARN, 0);
533 if (page == NULL)
534 return NULL;
535
536 tage = kmalloc(sizeof(*tage), gfp);
537 if (tage == NULL) {
538 __free_pages(page, 0);
539 return NULL;
540 }
541
542 tage->page = page;
543 atomic_inc(&trace_tage_allocated);
544
545 return tage;
546}
547
548static void
549tage_free(struct trace_page *tage)
550{
551 __ASSERT(tage != NULL);
552 __ASSERT(tage->page != NULL);
553
554 __free_pages(tage->page, 0);
555 kfree(tage);
556 atomic_dec(&trace_tage_allocated);
557}
558
559static struct trace_page *
560tage_from_list(struct list_head *list)
561{
562 return list_entry(list, struct trace_page, linkage);
563}
564
565static void
566tage_to_tail(struct trace_page *tage, struct list_head *queue)
567{
568 __ASSERT(tage != NULL);
569 __ASSERT(queue != NULL);
570
571 list_move_tail(&tage->linkage, queue);
572}
573
574/* try to return a page that has 'len' bytes left at the end */
575static struct trace_page *
576trace_get_tage_try(struct trace_cpu_data *tcd, unsigned long len)
577{
578 struct trace_page *tage;
579
580 if (tcd->tcd_cur_pages > 0) {
581 __ASSERT(!list_empty(&tcd->tcd_pages));
582 tage = tage_from_list(tcd->tcd_pages.prev);
583 if (tage->used + len <= PAGE_SIZE)
584 return tage;
585 }
586
587 if (tcd->tcd_cur_pages < tcd->tcd_max_pages) {
588 if (tcd->tcd_cur_stock_pages > 0) {
589 tage = tage_from_list(tcd->tcd_stock_pages.prev);
590 tcd->tcd_cur_stock_pages--;
591 list_del_init(&tage->linkage);
592 } else {
593 tage = tage_alloc(GFP_ATOMIC);
594 if (tage == NULL) {
595 printk(KERN_WARNING
596 "failure to allocate a tage (%ld)\n",
597 tcd->tcd_cur_pages);
598 return NULL;
599 }
600 }
601
602 tage->used = 0;
603 tage->cpu = smp_processor_id();
604 tage->type = tcd->tcd_type;
605 list_add_tail(&tage->linkage, &tcd->tcd_pages);
606 tcd->tcd_cur_pages++;
607
608 return tage;
609 }
610
611 return NULL;
612}
613
614/* return a page that has 'len' bytes left at the end */
615static struct trace_page *
616trace_get_tage(struct trace_cpu_data *tcd, unsigned long len)
617{
618 struct trace_page *tage;
619
620 __ASSERT(len <= PAGE_SIZE);
621
622 tage = trace_get_tage_try(tcd, len);
623 if (tage)
624 return tage;
625
626 if (tcd->tcd_cur_pages > 0) {
627 tage = tage_from_list(tcd->tcd_pages.next);
628 tage->used = 0;
629 tage_to_tail(tage, &tcd->tcd_pages);
630 }
631
632 return tage;
633}
634
635int
636spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask,
637 const char *file, const char *fn, const int line,
638 const char *format1, va_list args, const char *format2, ...)
639{
640 struct trace_cpu_data *tcd = NULL;
b02e9b24 641 struct spl_debug_header header = { 0, };
57d1b188 642 struct trace_page *tage;
643 /* string_buf is used only if tcd != NULL, and is always set then */
644 char *string_buf = NULL;
645 char *debug_buf;
646 int known_size;
647 int needed = 85; /* average message length */
648 int max_nob;
649 va_list ap;
650 int i;
651 int remain;
652
653 if (strchr(file, '/'))
654 file = strrchr(file, '/') + 1;
655
656 trace_set_debug_header(&header, subsys, mask, line, CDEBUG_STACK());
657
658 tcd = trace_get_tcd();
659 if (tcd == NULL)
660 goto console;
661
662 if (tcd->tcd_shutting_down) {
663 trace_put_tcd(tcd);
664 tcd = NULL;
665 goto console;
666 }
667
668 known_size = strlen(file) + 1;
669 if (fn)
670 known_size += strlen(fn) + 1;
671
672 if (spl_debug_binary)
673 known_size += sizeof(header);
674
675 /* '2' used because vsnprintf returns real size required for output
676 * _without_ terminating NULL. */
677 for (i = 0; i < 2; i++) {
678 tage = trace_get_tage(tcd, needed + known_size + 1);
679 if (tage == NULL) {
680 if (needed + known_size > PAGE_SIZE)
681 mask |= D_ERROR;
682
683 trace_put_tcd(tcd);
684 tcd = NULL;
685 goto console;
686 }
687
688 string_buf = (char *)page_address(tage->page) +
689 tage->used + known_size;
690
691 max_nob = PAGE_SIZE - tage->used - known_size;
692 if (max_nob <= 0) {
693 printk(KERN_EMERG "negative max_nob: %i\n", max_nob);
694 mask |= D_ERROR;
695 trace_put_tcd(tcd);
696 tcd = NULL;
697 goto console;
698 }
699
700 needed = 0;
701 if (format1) {
702 va_copy(ap, args);
703 needed = vsnprintf(string_buf, max_nob, format1, ap);
704 va_end(ap);
705 }
706
707 if (format2) {
708 remain = max_nob - needed;
709 if (remain < 0)
710 remain = 0;
711
712 va_start(ap, format2);
713 needed += vsnprintf(string_buf+needed, remain, format2, ap);
714 va_end(ap);
715 }
716
717 if (needed < max_nob)
718 break;
719 }
720
57d1b188 721 header.ph_len = known_size + needed;
722 debug_buf = (char *)page_address(tage->page) + tage->used;
723
724 if (spl_debug_binary) {
725 memcpy(debug_buf, &header, sizeof(header));
726 tage->used += sizeof(header);
727 debug_buf += sizeof(header);
728 }
729
730 strcpy(debug_buf, file);
731 tage->used += strlen(file) + 1;
732 debug_buf += strlen(file) + 1;
733
734 if (fn) {
735 strcpy(debug_buf, fn);
736 tage->used += strlen(fn) + 1;
737 debug_buf += strlen(fn) + 1;
738 }
739
740 __ASSERT(debug_buf == string_buf);
741
742 tage->used += needed;
743 __ASSERT (tage->used <= PAGE_SIZE);
744
745console:
746 if ((mask & spl_debug_printk) == 0) {
747 /* no console output requested */
748 if (tcd != NULL)
749 trace_put_tcd(tcd);
750 return 1;
751 }
752
753 if (cdls != NULL) {
754 if (spl_console_ratelimit && cdls->cdls_next != 0 &&
755 !time_before(cdls->cdls_next, jiffies)) {
756 /* skipping a console message */
757 cdls->cdls_count++;
758 if (tcd != NULL)
759 trace_put_tcd(tcd);
760 return 1;
761 }
762
763 if (time_before(cdls->cdls_next + spl_console_max_delay +
764 (10 * HZ), jiffies)) {
765 /* last timeout was a long time ago */
766 cdls->cdls_delay /= spl_console_backoff * 4;
767 } else {
768 cdls->cdls_delay *= spl_console_backoff;
769
770 if (cdls->cdls_delay < spl_console_min_delay)
771 cdls->cdls_delay = spl_console_min_delay;
772 else if (cdls->cdls_delay > spl_console_max_delay)
773 cdls->cdls_delay = spl_console_max_delay;
774 }
775
776 /* ensure cdls_next is never zero after it's been seen */
777 cdls->cdls_next = (jiffies + cdls->cdls_delay) | 1;
778 }
779
780 if (tcd != NULL) {
781 trace_print_to_console(&header, mask, string_buf, needed, file, fn);
782 trace_put_tcd(tcd);
783 } else {
784 string_buf = trace_get_console_buffer();
785
786 needed = 0;
787 if (format1 != NULL) {
788 va_copy(ap, args);
789 needed = vsnprintf(string_buf, TRACE_CONSOLE_BUFFER_SIZE, format1, ap);
790 va_end(ap);
791 }
792 if (format2 != NULL) {
793 remain = TRACE_CONSOLE_BUFFER_SIZE - needed;
794 if (remain > 0) {
795 va_start(ap, format2);
796 needed += vsnprintf(string_buf+needed, remain, format2, ap);
797 va_end(ap);
798 }
799 }
800 trace_print_to_console(&header, mask,
801 string_buf, needed, file, fn);
802
803 trace_put_console_buffer(string_buf);
804 }
805
806 if (cdls != NULL && cdls->cdls_count != 0) {
807 string_buf = trace_get_console_buffer();
808
809 needed = snprintf(string_buf, TRACE_CONSOLE_BUFFER_SIZE,
810 "Skipped %d previous similar message%s\n",
811 cdls->cdls_count, (cdls->cdls_count > 1) ? "s" : "");
812
813 trace_print_to_console(&header, mask,
814 string_buf, needed, file, fn);
815
816 trace_put_console_buffer(string_buf);
817 cdls->cdls_count = 0;
818 }
819
820 return 0;
821}
822EXPORT_SYMBOL(spl_debug_vmsg);
823
824/* Do the collect_pages job on a single CPU: assumes that all other
825 * CPUs have been stopped during a panic. If this isn't true for
826 * some arch, this will have to be implemented separately in each arch.
827 */
828static void
7fea96c0 829collect_pages_from_single_cpu(struct page_collection *pc)
57d1b188 830{
831 struct trace_cpu_data *tcd;
832 int i, j;
833
834 tcd_for_each(tcd, i, j) {
835 list_splice_init(&tcd->tcd_pages, &pc->pc_pages);
836 tcd->tcd_cur_pages = 0;
837 }
838}
839
840static void
f6c81c5e 841collect_pages_on_all_cpus(struct page_collection *pc)
57d1b188 842{
843 struct trace_cpu_data *tcd;
f6c81c5e 844 int i, cpu;
57d1b188 845
846 spin_lock(&pc->pc_lock);
f6c81c5e 847 for_each_possible_cpu(cpu) {
848 tcd_for_each_type_lock(tcd, i, cpu) {
849 list_splice_init(&tcd->tcd_pages, &pc->pc_pages);
850 tcd->tcd_cur_pages = 0;
851 }
57d1b188 852 }
853 spin_unlock(&pc->pc_lock);
854}
855
856static void
7fea96c0 857collect_pages(dumplog_priv_t *dp, struct page_collection *pc)
57d1b188 858{
859 INIT_LIST_HEAD(&pc->pc_pages);
860
7fea96c0 861 if (spl_panic_in_progress || dp->dp_flags & DL_SINGLE_CPU)
862 collect_pages_from_single_cpu(pc);
57d1b188 863 else
f6c81c5e 864 collect_pages_on_all_cpus(pc);
57d1b188 865}
866
867static void
f6c81c5e 868put_pages_back_on_all_cpus(struct page_collection *pc)
57d1b188 869{
57d1b188 870 struct trace_cpu_data *tcd;
871 struct list_head *cur_head;
872 struct trace_page *tage;
873 struct trace_page *tmp;
f6c81c5e 874 int i, cpu;
57d1b188 875
876 spin_lock(&pc->pc_lock);
57d1b188 877
f6c81c5e 878 for_each_possible_cpu(cpu) {
879 tcd_for_each_type_lock(tcd, i, cpu) {
880 cur_head = tcd->tcd_pages.next;
57d1b188 881
f6c81c5e 882 list_for_each_entry_safe(tage, tmp, &pc->pc_pages,
883 linkage) {
57d1b188 884
f6c81c5e 885 __ASSERT_TAGE_INVARIANT(tage);
886
887 if (tage->cpu != cpu || tage->type != i)
888 continue;
57d1b188 889
f6c81c5e 890 tage_to_tail(tage, cur_head);
891 tcd->tcd_cur_pages++;
892 }
57d1b188 893 }
894 }
f6c81c5e 895
57d1b188 896 spin_unlock(&pc->pc_lock);
897}
898
899static void
900put_pages_back(struct page_collection *pc)
901{
902 if (!spl_panic_in_progress)
f6c81c5e 903 put_pages_back_on_all_cpus(pc);
57d1b188 904}
905
57d1b188 906static int
7fea96c0 907spl_debug_dump_all_pages(dumplog_priv_t *dp, char *filename)
57d1b188 908{
909 struct page_collection pc;
910 struct file *filp;
911 struct trace_page *tage;
912 struct trace_page *tmp;
913 mm_segment_t oldfs;
914 int rc = 0;
915
916 down_write(&trace_sem);
917
f0ff89fc 918 filp = spl_filp_open(filename, O_CREAT|O_EXCL|O_WRONLY|O_LARGEFILE,
57d1b188 919 0600, &rc);
920 if (filp == NULL) {
921 if (rc != -EEXIST)
922 printk(KERN_ERR "SPL: Can't open %s for dump: %d\n",
923 filename, rc);
924 goto out;
925 }
926
927 spin_lock_init(&pc.pc_lock);
7fea96c0 928 collect_pages(dp, &pc);
57d1b188 929 if (list_empty(&pc.pc_pages)) {
930 rc = 0;
931 goto close;
932 }
933
934 oldfs = get_fs();
935 set_fs(get_ds());
936
937 list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) {
938 __ASSERT_TAGE_INVARIANT(tage);
939
f0ff89fc
BB
940 rc = spl_filp_write(filp, page_address(tage->page),
941 tage->used, spl_filp_poff(filp));
57d1b188 942 if (rc != (int)tage->used) {
943 printk(KERN_WARNING "SPL: Wanted to write %u "
944 "but wrote %d\n", tage->used, rc);
945 put_pages_back(&pc);
946 __ASSERT(list_empty(&pc.pc_pages));
947 break;
948 }
949 list_del(&tage->linkage);
950 tage_free(tage);
951 }
952
953 set_fs(oldfs);
954
f0ff89fc 955 rc = spl_filp_fsync(filp, 1);
57d1b188 956 if (rc)
957 printk(KERN_ERR "SPL: Unable to sync: %d\n", rc);
958 close:
f0ff89fc 959 spl_filp_close(filp);
57d1b188 960 out:
961 up_write(&trace_sem);
962
963 return rc;
964}
965
966static void
967spl_debug_flush_pages(void)
968{
7fea96c0 969 dumplog_priv_t dp;
57d1b188 970 struct page_collection pc;
971 struct trace_page *tage;
972 struct trace_page *tmp;
973
974 spin_lock_init(&pc.pc_lock);
7fea96c0 975 init_waitqueue_head(&dp.dp_waitq);
976 dp.dp_pid = current->pid;
977 dp.dp_flags = 0;
978 atomic_set(&dp.dp_done, 0);
57d1b188 979
7fea96c0 980 collect_pages(&dp, &pc);
57d1b188 981 list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) {
982 __ASSERT_TAGE_INVARIANT(tage);
983 list_del(&tage->linkage);
984 tage_free(tage);
985 }
986}
987
988unsigned long
989spl_debug_set_mask(unsigned long mask) {
990 spl_debug_mask = mask;
991 return 0;
992}
993EXPORT_SYMBOL(spl_debug_set_mask);
994
995unsigned long
996spl_debug_get_mask(void) {
997 return spl_debug_mask;
998}
999EXPORT_SYMBOL(spl_debug_get_mask);
1000
1001unsigned long
1002spl_debug_set_subsys(unsigned long subsys) {
1003 spl_debug_subsys = subsys;
1004 return 0;
1005}
1006EXPORT_SYMBOL(spl_debug_set_subsys);
1007
1008unsigned long
1009spl_debug_get_subsys(void) {
1010 return spl_debug_subsys;
1011}
1012EXPORT_SYMBOL(spl_debug_get_subsys);
1013
1014int
1015spl_debug_set_mb(int mb)
1016{
1017 int i, j, pages;
1018 int limit = trace_max_debug_mb();
1019 struct trace_cpu_data *tcd;
1020
1021 if (mb < num_possible_cpus()) {
1022 printk(KERN_ERR "SPL: Refusing to set debug buffer size to "
1023 "%dMB - lower limit is %d\n", mb, num_possible_cpus());
1024 return -EINVAL;
1025 }
1026
1027 if (mb > limit) {
1028 printk(KERN_ERR "SPL: Refusing to set debug buffer size to "
1029 "%dMB - upper limit is %d\n", mb, limit);
1030 return -EINVAL;
1031 }
1032
1033 mb /= num_possible_cpus();
1034 pages = mb << (20 - PAGE_SHIFT);
1035
1036 down_write(&trace_sem);
1037
1038 tcd_for_each(tcd, i, j)
1039 tcd->tcd_max_pages = (pages * tcd->tcd_pages_factor) / 100;
1040
1041 up_write(&trace_sem);
1042
1043 return 0;
1044}
1045EXPORT_SYMBOL(spl_debug_set_mb);
1046
1047int
1048spl_debug_get_mb(void)
1049{
1050 int i, j;
1051 struct trace_cpu_data *tcd;
1052 int total_pages = 0;
1053
1054 down_read(&trace_sem);
1055
1056 tcd_for_each(tcd, i, j)
1057 total_pages += tcd->tcd_max_pages;
1058
1059 up_read(&trace_sem);
1060
1061 return (total_pages >> (20 - PAGE_SHIFT)) + 1;
1062}
1063EXPORT_SYMBOL(spl_debug_get_mb);
1064
1065void spl_debug_dumpstack(struct task_struct *tsk)
1066{
1067 extern void show_task(struct task_struct *);
1068
1069 if (tsk == NULL)
1070 tsk = current;
1071
627a7497 1072 printk("SPL: Showing stack for process %d\n", tsk->pid);
57d86234 1073 dump_stack();
57d1b188 1074}
1075EXPORT_SYMBOL(spl_debug_dumpstack);
1076
7fea96c0 1077void spl_debug_bug(char *file, const char *func, const int line, int flags)
57d1b188 1078{
1079 spl_debug_catastrophe = 1;
937879f1 1080 spl_debug_msg(NULL, 0, D_EMERG, file, func, line, "SBUG\n");
57d1b188 1081
1082 if (in_interrupt()) {
937879f1 1083 panic("SBUG in interrupt.\n");
57d1b188 1084 /* not reached */
1085 }
1086
97f8f6d7
BB
1087 if (in_atomic() || irqs_disabled())
1088 flags |= DL_NOTHREAD;
1089
57d1b188 1090 /* Ensure all debug pages and dumped by current cpu */
1091 if (spl_debug_panic_on_bug)
1092 spl_panic_in_progress = 1;
1093
1094 spl_debug_dumpstack(NULL);
7fea96c0 1095 spl_debug_dumplog(flags);
57d1b188 1096
1097 if (spl_debug_panic_on_bug)
937879f1 1098 panic("SBUG");
57d1b188 1099
1100 set_task_state(current, TASK_UNINTERRUPTIBLE);
1101 while (1)
1102 schedule();
1103}
1104EXPORT_SYMBOL(spl_debug_bug);
1105
1106int
1107spl_debug_clear_buffer(void)
1108{
1109 spl_debug_flush_pages();
1110 return 0;
1111}
1112EXPORT_SYMBOL(spl_debug_clear_buffer);
1113
1114int
1115spl_debug_mark_buffer(char *text)
1116{
1117 CDEBUG(D_WARNING, "*************************************\n");
1118 CDEBUG(D_WARNING, "DEBUG MARKER: %s\n", text);
1119 CDEBUG(D_WARNING, "*************************************\n");
1120
1121 return 0;
1122}
1123EXPORT_SYMBOL(spl_debug_mark_buffer);
1124
57d1b188 1125static int
1126trace_init(int max_pages)
1127{
1128 struct trace_cpu_data *tcd;
1129 int i, j;
1130
1131 init_rwsem(&trace_sem);
1132
1133 /* initialize trace_data */
1134 memset(trace_data, 0, sizeof(trace_data));
1135 for (i = 0; i < TCD_TYPE_MAX; i++) {
1136 trace_data[i] = kmalloc(sizeof(union trace_data_union) *
1137 NR_CPUS, GFP_KERNEL);
1138 if (trace_data[i] == NULL)
1139 goto out;
1140 }
1141
1142 tcd_for_each(tcd, i, j) {
f6c81c5e 1143 spin_lock_init(&tcd->tcd_lock);
57d1b188 1144 tcd->tcd_pages_factor = pages_factor[i];
1145 tcd->tcd_type = i;
1146 tcd->tcd_cpu = j;
1147 INIT_LIST_HEAD(&tcd->tcd_pages);
1148 INIT_LIST_HEAD(&tcd->tcd_stock_pages);
1149 tcd->tcd_cur_pages = 0;
1150 tcd->tcd_cur_stock_pages = 0;
1151 tcd->tcd_max_pages = (max_pages * pages_factor[i]) / 100;
1152 tcd->tcd_shutting_down = 0;
1153 }
1154
1155 for (i = 0; i < num_possible_cpus(); i++) {
1156 for (j = 0; j < 3; j++) {
1157 trace_console_buffers[i][j] =
1158 kmalloc(TRACE_CONSOLE_BUFFER_SIZE,
1159 GFP_KERNEL);
1160
1161 if (trace_console_buffers[i][j] == NULL)
1162 goto out;
1163 }
1164 }
1165
1166 return 0;
1167out:
1168 trace_fini();
1169 printk(KERN_ERR "SPL: Insufficient memory for debug logs\n");
1170 return -ENOMEM;
1171}
1172
1173int
1174debug_init(void)
1175{
1176 int rc, max = spl_debug_mb;
1177
1178 spl_console_max_delay = SPL_DEFAULT_MAX_DELAY;
1179 spl_console_min_delay = SPL_DEFAULT_MIN_DELAY;
1180
1181 /* If spl_debug_mb is set to an invalid value or uninitialized
1182 * then just make the total buffers smp_num_cpus TCD_MAX_PAGES */
1183 if (max > (num_physpages >> (20 - 2 - PAGE_SHIFT)) / 5 ||
1184 max >= 512 || max < 0) {
1185 max = TCD_MAX_PAGES;
1186 } else {
1187 max = (max / num_online_cpus()) << (20 - PAGE_SHIFT);
1188 }
1189
1190 rc = trace_init(max);
1191 if (rc)
1192 return rc;
1193
d50bd9e2 1194 return rc;
57d1b188 1195}
1196
1197static void
f6c81c5e 1198trace_cleanup_on_all_cpus(void)
57d1b188 1199{
1200 struct trace_cpu_data *tcd;
1201 struct trace_page *tage;
1202 struct trace_page *tmp;
f6c81c5e 1203 int i, cpu;
57d1b188 1204
f6c81c5e 1205 for_each_possible_cpu(cpu) {
1206 tcd_for_each_type_lock(tcd, i, cpu) {
1207 tcd->tcd_shutting_down = 1;
57d1b188 1208
f6c81c5e 1209 list_for_each_entry_safe(tage, tmp, &tcd->tcd_pages,
1210 linkage) {
1211 __ASSERT_TAGE_INVARIANT(tage);
57d1b188 1212
f6c81c5e 1213 list_del(&tage->linkage);
1214 tage_free(tage);
1215 }
1216 tcd->tcd_cur_pages = 0;
57d1b188 1217 }
57d1b188 1218 }
1219}
1220
1221static void
1222trace_fini(void)
1223{
1224 int i, j;
1225
f6c81c5e 1226 trace_cleanup_on_all_cpus();
57d1b188 1227
1228 for (i = 0; i < num_possible_cpus(); i++) {
1229 for (j = 0; j < 3; j++) {
1230 if (trace_console_buffers[i][j] != NULL) {
1231 kfree(trace_console_buffers[i][j]);
1232 trace_console_buffers[i][j] = NULL;
1233 }
1234 }
1235 }
1236
124ca8a5 1237 for (i = 0; i < TCD_TYPE_MAX && trace_data[i] != NULL; i++) {
57d1b188 1238 kfree(trace_data[i]);
1239 trace_data[i] = NULL;
1240 }
1241}
1242
1243void
1244debug_fini(void)
1245{
57d1b188 1246 trace_fini();
57d1b188 1247}