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