This source file includes following definitions.
- trim_prefix
- ddebug_describe_flags
- vpr_info_dq
- ddebug_change
- ddebug_tokenize
- parse_lineno
- check_set
- ddebug_parse_query
- ddebug_parse_flags
- ddebug_exec_query
- ddebug_exec_queries
- remaining
- dynamic_emit_prefix
- __dynamic_pr_debug
- __dynamic_dev_dbg
- __dynamic_netdev_dbg
- __dynamic_ibdev_dbg
- ddebug_setup_query
- ddebug_proc_write
- ddebug_iter_first
- ddebug_iter_next
- ddebug_proc_start
- ddebug_proc_next
- ddebug_proc_show
- ddebug_proc_stop
- ddebug_proc_open
- ddebug_add_module
- ddebug_dyndbg_param_cb
- ddebug_dyndbg_boot_param_cb
- ddebug_dyndbg_module_param_cb
- ddebug_table_free
- ddebug_remove_module
- ddebug_remove_all_tables
- dynamic_debug_init_debugfs
- dynamic_debug_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/kallsyms.h>
20 #include <linux/types.h>
21 #include <linux/mutex.h>
22 #include <linux/proc_fs.h>
23 #include <linux/seq_file.h>
24 #include <linux/list.h>
25 #include <linux/sysctl.h>
26 #include <linux/ctype.h>
27 #include <linux/string.h>
28 #include <linux/parser.h>
29 #include <linux/string_helpers.h>
30 #include <linux/uaccess.h>
31 #include <linux/dynamic_debug.h>
32 #include <linux/debugfs.h>
33 #include <linux/slab.h>
34 #include <linux/jump_label.h>
35 #include <linux/hardirq.h>
36 #include <linux/sched.h>
37 #include <linux/device.h>
38 #include <linux/netdevice.h>
39
40 #include <rdma/ib_verbs.h>
41
42 extern struct _ddebug __start___verbose[];
43 extern struct _ddebug __stop___verbose[];
44
45 struct ddebug_table {
46 struct list_head link;
47 const char *mod_name;
48 unsigned int num_ddebugs;
49 struct _ddebug *ddebugs;
50 };
51
52 struct ddebug_query {
53 const char *filename;
54 const char *module;
55 const char *function;
56 const char *format;
57 unsigned int first_lineno, last_lineno;
58 };
59
60 struct ddebug_iter {
61 struct ddebug_table *table;
62 unsigned int idx;
63 };
64
65 static DEFINE_MUTEX(ddebug_lock);
66 static LIST_HEAD(ddebug_tables);
67 static int verbose;
68 module_param(verbose, int, 0644);
69
70
71 static inline const char *trim_prefix(const char *path)
72 {
73 int skip = strlen(__FILE__) - strlen("lib/dynamic_debug.c");
74
75 if (strncmp(path, __FILE__, skip))
76 skip = 0;
77
78 return path + skip;
79 }
80
81 static struct { unsigned flag:8; char opt_char; } opt_array[] = {
82 { _DPRINTK_FLAGS_PRINT, 'p' },
83 { _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
84 { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
85 { _DPRINTK_FLAGS_INCL_LINENO, 'l' },
86 { _DPRINTK_FLAGS_INCL_TID, 't' },
87 { _DPRINTK_FLAGS_NONE, '_' },
88 };
89
90
91 static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
92 size_t maxlen)
93 {
94 char *p = buf;
95 int i;
96
97 BUG_ON(maxlen < 6);
98 for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
99 if (dp->flags & opt_array[i].flag)
100 *p++ = opt_array[i].opt_char;
101 if (p == buf)
102 *p++ = '_';
103 *p = '\0';
104
105 return buf;
106 }
107
108 #define vpr_info(fmt, ...) \
109 do { \
110 if (verbose) \
111 pr_info(fmt, ##__VA_ARGS__); \
112 } while (0)
113
114 static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
115 {
116
117 int fmtlen = 0;
118
119 if (query->format) {
120 fmtlen = strlen(query->format);
121 while (fmtlen && query->format[fmtlen - 1] == '\n')
122 fmtlen--;
123 }
124
125 vpr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
126 msg,
127 query->function ? query->function : "",
128 query->filename ? query->filename : "",
129 query->module ? query->module : "",
130 fmtlen, query->format ? query->format : "",
131 query->first_lineno, query->last_lineno);
132 }
133
134
135
136
137
138
139
140 static int ddebug_change(const struct ddebug_query *query,
141 unsigned int flags, unsigned int mask)
142 {
143 int i;
144 struct ddebug_table *dt;
145 unsigned int newflags;
146 unsigned int nfound = 0;
147 char flagbuf[10];
148
149
150 mutex_lock(&ddebug_lock);
151 list_for_each_entry(dt, &ddebug_tables, link) {
152
153
154 if (query->module &&
155 !match_wildcard(query->module, dt->mod_name))
156 continue;
157
158 for (i = 0; i < dt->num_ddebugs; i++) {
159 struct _ddebug *dp = &dt->ddebugs[i];
160
161
162 if (query->filename &&
163 !match_wildcard(query->filename, dp->filename) &&
164 !match_wildcard(query->filename,
165 kbasename(dp->filename)) &&
166 !match_wildcard(query->filename,
167 trim_prefix(dp->filename)))
168 continue;
169
170
171 if (query->function &&
172 !match_wildcard(query->function, dp->function))
173 continue;
174
175
176 if (query->format &&
177 !strstr(dp->format, query->format))
178 continue;
179
180
181 if (query->first_lineno &&
182 dp->lineno < query->first_lineno)
183 continue;
184 if (query->last_lineno &&
185 dp->lineno > query->last_lineno)
186 continue;
187
188 nfound++;
189
190 newflags = (dp->flags & mask) | flags;
191 if (newflags == dp->flags)
192 continue;
193 #ifdef CONFIG_JUMP_LABEL
194 if (dp->flags & _DPRINTK_FLAGS_PRINT) {
195 if (!(flags & _DPRINTK_FLAGS_PRINT))
196 static_branch_disable(&dp->key.dd_key_true);
197 } else if (flags & _DPRINTK_FLAGS_PRINT)
198 static_branch_enable(&dp->key.dd_key_true);
199 #endif
200 dp->flags = newflags;
201 vpr_info("changed %s:%d [%s]%s =%s\n",
202 trim_prefix(dp->filename), dp->lineno,
203 dt->mod_name, dp->function,
204 ddebug_describe_flags(dp, flagbuf,
205 sizeof(flagbuf)));
206 }
207 }
208 mutex_unlock(&ddebug_lock);
209
210 if (!nfound && verbose)
211 pr_info("no matches for query\n");
212
213 return nfound;
214 }
215
216
217
218
219
220
221
222 static int ddebug_tokenize(char *buf, char *words[], int maxwords)
223 {
224 int nwords = 0;
225
226 while (*buf) {
227 char *end;
228
229
230 buf = skip_spaces(buf);
231 if (!*buf)
232 break;
233 if (*buf == '#')
234 break;
235
236
237 if (*buf == '"' || *buf == '\'') {
238 int quote = *buf++;
239 for (end = buf; *end && *end != quote; end++)
240 ;
241 if (!*end) {
242 pr_err("unclosed quote: %s\n", buf);
243 return -EINVAL;
244 }
245 } else {
246 for (end = buf; *end && !isspace(*end); end++)
247 ;
248 BUG_ON(end == buf);
249 }
250
251
252 if (nwords == maxwords) {
253 pr_err("too many words, legal max <=%d\n", maxwords);
254 return -EINVAL;
255 }
256 if (*end)
257 *end++ = '\0';
258 words[nwords++] = buf;
259 buf = end;
260 }
261
262 if (verbose) {
263 int i;
264 pr_info("split into words:");
265 for (i = 0; i < nwords; i++)
266 pr_cont(" \"%s\"", words[i]);
267 pr_cont("\n");
268 }
269
270 return nwords;
271 }
272
273
274
275
276
277
278 static inline int parse_lineno(const char *str, unsigned int *val)
279 {
280 BUG_ON(str == NULL);
281 if (*str == '\0') {
282 *val = 0;
283 return 0;
284 }
285 if (kstrtouint(str, 10, val) < 0) {
286 pr_err("bad line-number: %s\n", str);
287 return -EINVAL;
288 }
289 return 0;
290 }
291
292 static int check_set(const char **dest, char *src, char *name)
293 {
294 int rc = 0;
295
296 if (*dest) {
297 rc = -EINVAL;
298 pr_err("match-spec:%s val:%s overridden by %s\n",
299 name, *dest, src);
300 }
301 *dest = src;
302 return rc;
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 static int ddebug_parse_query(char *words[], int nwords,
321 struct ddebug_query *query, const char *modname)
322 {
323 unsigned int i;
324 int rc = 0;
325
326
327 if (nwords % 2 != 0) {
328 pr_err("expecting pairs of match-spec <value>\n");
329 return -EINVAL;
330 }
331 memset(query, 0, sizeof(*query));
332
333 if (modname)
334
335 query->module = modname;
336
337 for (i = 0; i < nwords; i += 2) {
338 if (!strcmp(words[i], "func")) {
339 rc = check_set(&query->function, words[i+1], "func");
340 } else if (!strcmp(words[i], "file")) {
341 rc = check_set(&query->filename, words[i+1], "file");
342 } else if (!strcmp(words[i], "module")) {
343 rc = check_set(&query->module, words[i+1], "module");
344 } else if (!strcmp(words[i], "format")) {
345 string_unescape_inplace(words[i+1], UNESCAPE_SPACE |
346 UNESCAPE_OCTAL |
347 UNESCAPE_SPECIAL);
348 rc = check_set(&query->format, words[i+1], "format");
349 } else if (!strcmp(words[i], "line")) {
350 char *first = words[i+1];
351 char *last = strchr(first, '-');
352 if (query->first_lineno || query->last_lineno) {
353 pr_err("match-spec: line used 2x\n");
354 return -EINVAL;
355 }
356 if (last)
357 *last++ = '\0';
358 if (parse_lineno(first, &query->first_lineno) < 0)
359 return -EINVAL;
360 if (last) {
361
362 if (parse_lineno(last, &query->last_lineno) < 0)
363 return -EINVAL;
364
365
366 if (query->last_lineno == 0)
367 query->last_lineno = UINT_MAX;
368
369 if (query->last_lineno < query->first_lineno) {
370 pr_err("last-line:%d < 1st-line:%d\n",
371 query->last_lineno,
372 query->first_lineno);
373 return -EINVAL;
374 }
375 } else {
376 query->last_lineno = query->first_lineno;
377 }
378 } else {
379 pr_err("unknown keyword \"%s\"\n", words[i]);
380 return -EINVAL;
381 }
382 if (rc)
383 return rc;
384 }
385 vpr_info_dq(query, "parsed");
386 return 0;
387 }
388
389
390
391
392
393
394
395 static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
396 unsigned int *maskp)
397 {
398 unsigned flags = 0;
399 int op = '=', i;
400
401 switch (*str) {
402 case '+':
403 case '-':
404 case '=':
405 op = *str++;
406 break;
407 default:
408 pr_err("bad flag-op %c, at start of %s\n", *str, str);
409 return -EINVAL;
410 }
411 vpr_info("op='%c'\n", op);
412
413 for (; *str ; ++str) {
414 for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
415 if (*str == opt_array[i].opt_char) {
416 flags |= opt_array[i].flag;
417 break;
418 }
419 }
420 if (i < 0) {
421 pr_err("unknown flag '%c' in \"%s\"\n", *str, str);
422 return -EINVAL;
423 }
424 }
425 vpr_info("flags=0x%x\n", flags);
426
427
428 switch (op) {
429 case '=':
430 *maskp = 0;
431 *flagsp = flags;
432 break;
433 case '+':
434 *maskp = ~0U;
435 *flagsp = flags;
436 break;
437 case '-':
438 *maskp = ~flags;
439 *flagsp = 0;
440 break;
441 }
442 vpr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
443 return 0;
444 }
445
446 static int ddebug_exec_query(char *query_string, const char *modname)
447 {
448 unsigned int flags = 0, mask = 0;
449 struct ddebug_query query;
450 #define MAXWORDS 9
451 int nwords, nfound;
452 char *words[MAXWORDS];
453
454 nwords = ddebug_tokenize(query_string, words, MAXWORDS);
455 if (nwords <= 0) {
456 pr_err("tokenize failed\n");
457 return -EINVAL;
458 }
459
460 if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) {
461 pr_err("flags parse failed\n");
462 return -EINVAL;
463 }
464 if (ddebug_parse_query(words, nwords-1, &query, modname)) {
465 pr_err("query parse failed\n");
466 return -EINVAL;
467 }
468
469 nfound = ddebug_change(&query, flags, mask);
470 vpr_info_dq(&query, nfound ? "applied" : "no-match");
471
472 return nfound;
473 }
474
475
476
477
478
479 static int ddebug_exec_queries(char *query, const char *modname)
480 {
481 char *split;
482 int i, errs = 0, exitcode = 0, rc, nfound = 0;
483
484 for (i = 0; query; query = split) {
485 split = strpbrk(query, ";\n");
486 if (split)
487 *split++ = '\0';
488
489 query = skip_spaces(query);
490 if (!query || !*query || *query == '#')
491 continue;
492
493 vpr_info("query %d: \"%s\"\n", i, query);
494
495 rc = ddebug_exec_query(query, modname);
496 if (rc < 0) {
497 errs++;
498 exitcode = rc;
499 } else {
500 nfound += rc;
501 }
502 i++;
503 }
504 vpr_info("processed %d queries, with %d matches, %d errs\n",
505 i, nfound, errs);
506
507 if (exitcode)
508 return exitcode;
509 return nfound;
510 }
511
512 #define PREFIX_SIZE 64
513
514 static int remaining(int wrote)
515 {
516 if (PREFIX_SIZE - wrote > 0)
517 return PREFIX_SIZE - wrote;
518 return 0;
519 }
520
521 static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
522 {
523 int pos_after_tid;
524 int pos = 0;
525
526 *buf = '\0';
527
528 if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
529 if (in_interrupt())
530 pos += snprintf(buf + pos, remaining(pos), "<intr> ");
531 else
532 pos += snprintf(buf + pos, remaining(pos), "[%d] ",
533 task_pid_vnr(current));
534 }
535 pos_after_tid = pos;
536 if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
537 pos += snprintf(buf + pos, remaining(pos), "%s:",
538 desc->modname);
539 if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
540 pos += snprintf(buf + pos, remaining(pos), "%s:",
541 desc->function);
542 if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
543 pos += snprintf(buf + pos, remaining(pos), "%d:",
544 desc->lineno);
545 if (pos - pos_after_tid)
546 pos += snprintf(buf + pos, remaining(pos), " ");
547 if (pos >= PREFIX_SIZE)
548 buf[PREFIX_SIZE - 1] = '\0';
549
550 return buf;
551 }
552
553 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
554 {
555 va_list args;
556 struct va_format vaf;
557 char buf[PREFIX_SIZE];
558
559 BUG_ON(!descriptor);
560 BUG_ON(!fmt);
561
562 va_start(args, fmt);
563
564 vaf.fmt = fmt;
565 vaf.va = &args;
566
567 printk(KERN_DEBUG "%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf);
568
569 va_end(args);
570 }
571 EXPORT_SYMBOL(__dynamic_pr_debug);
572
573 void __dynamic_dev_dbg(struct _ddebug *descriptor,
574 const struct device *dev, const char *fmt, ...)
575 {
576 struct va_format vaf;
577 va_list args;
578
579 BUG_ON(!descriptor);
580 BUG_ON(!fmt);
581
582 va_start(args, fmt);
583
584 vaf.fmt = fmt;
585 vaf.va = &args;
586
587 if (!dev) {
588 printk(KERN_DEBUG "(NULL device *): %pV", &vaf);
589 } else {
590 char buf[PREFIX_SIZE];
591
592 dev_printk_emit(LOGLEVEL_DEBUG, dev, "%s%s %s: %pV",
593 dynamic_emit_prefix(descriptor, buf),
594 dev_driver_string(dev), dev_name(dev),
595 &vaf);
596 }
597
598 va_end(args);
599 }
600 EXPORT_SYMBOL(__dynamic_dev_dbg);
601
602 #ifdef CONFIG_NET
603
604 void __dynamic_netdev_dbg(struct _ddebug *descriptor,
605 const struct net_device *dev, const char *fmt, ...)
606 {
607 struct va_format vaf;
608 va_list args;
609
610 BUG_ON(!descriptor);
611 BUG_ON(!fmt);
612
613 va_start(args, fmt);
614
615 vaf.fmt = fmt;
616 vaf.va = &args;
617
618 if (dev && dev->dev.parent) {
619 char buf[PREFIX_SIZE];
620
621 dev_printk_emit(LOGLEVEL_DEBUG, dev->dev.parent,
622 "%s%s %s %s%s: %pV",
623 dynamic_emit_prefix(descriptor, buf),
624 dev_driver_string(dev->dev.parent),
625 dev_name(dev->dev.parent),
626 netdev_name(dev), netdev_reg_state(dev),
627 &vaf);
628 } else if (dev) {
629 printk(KERN_DEBUG "%s%s: %pV", netdev_name(dev),
630 netdev_reg_state(dev), &vaf);
631 } else {
632 printk(KERN_DEBUG "(NULL net_device): %pV", &vaf);
633 }
634
635 va_end(args);
636 }
637 EXPORT_SYMBOL(__dynamic_netdev_dbg);
638
639 #endif
640
641 #if IS_ENABLED(CONFIG_INFINIBAND)
642
643 void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
644 const struct ib_device *ibdev, const char *fmt, ...)
645 {
646 struct va_format vaf;
647 va_list args;
648
649 va_start(args, fmt);
650
651 vaf.fmt = fmt;
652 vaf.va = &args;
653
654 if (ibdev && ibdev->dev.parent) {
655 char buf[PREFIX_SIZE];
656
657 dev_printk_emit(LOGLEVEL_DEBUG, ibdev->dev.parent,
658 "%s%s %s %s: %pV",
659 dynamic_emit_prefix(descriptor, buf),
660 dev_driver_string(ibdev->dev.parent),
661 dev_name(ibdev->dev.parent),
662 dev_name(&ibdev->dev),
663 &vaf);
664 } else if (ibdev) {
665 printk(KERN_DEBUG "%s: %pV", dev_name(&ibdev->dev), &vaf);
666 } else {
667 printk(KERN_DEBUG "(NULL ib_device): %pV", &vaf);
668 }
669
670 va_end(args);
671 }
672 EXPORT_SYMBOL(__dynamic_ibdev_dbg);
673
674 #endif
675
676 #define DDEBUG_STRING_SIZE 1024
677 static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE];
678
679 static __init int ddebug_setup_query(char *str)
680 {
681 if (strlen(str) >= DDEBUG_STRING_SIZE) {
682 pr_warn("ddebug boot param string too large\n");
683 return 0;
684 }
685 strlcpy(ddebug_setup_string, str, DDEBUG_STRING_SIZE);
686 return 1;
687 }
688
689 __setup("ddebug_query=", ddebug_setup_query);
690
691
692
693
694
695 #define USER_BUF_PAGE 4096
696 static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
697 size_t len, loff_t *offp)
698 {
699 char *tmpbuf;
700 int ret;
701
702 if (len == 0)
703 return 0;
704 if (len > USER_BUF_PAGE - 1) {
705 pr_warn("expected <%d bytes into control\n", USER_BUF_PAGE);
706 return -E2BIG;
707 }
708 tmpbuf = memdup_user_nul(ubuf, len);
709 if (IS_ERR(tmpbuf))
710 return PTR_ERR(tmpbuf);
711 vpr_info("read %d bytes from userspace\n", (int)len);
712
713 ret = ddebug_exec_queries(tmpbuf, NULL);
714 kfree(tmpbuf);
715 if (ret < 0)
716 return ret;
717
718 *offp += len;
719 return len;
720 }
721
722
723
724
725
726
727 static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
728 {
729 if (list_empty(&ddebug_tables)) {
730 iter->table = NULL;
731 iter->idx = 0;
732 return NULL;
733 }
734 iter->table = list_entry(ddebug_tables.next,
735 struct ddebug_table, link);
736 iter->idx = 0;
737 return &iter->table->ddebugs[iter->idx];
738 }
739
740
741
742
743
744
745
746 static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
747 {
748 if (iter->table == NULL)
749 return NULL;
750 if (++iter->idx == iter->table->num_ddebugs) {
751
752 iter->idx = 0;
753 if (list_is_last(&iter->table->link, &ddebug_tables)) {
754 iter->table = NULL;
755 return NULL;
756 }
757 iter->table = list_entry(iter->table->link.next,
758 struct ddebug_table, link);
759 }
760 return &iter->table->ddebugs[iter->idx];
761 }
762
763
764
765
766
767
768 static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
769 {
770 struct ddebug_iter *iter = m->private;
771 struct _ddebug *dp;
772 int n = *pos;
773
774 vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
775
776 mutex_lock(&ddebug_lock);
777
778 if (!n)
779 return SEQ_START_TOKEN;
780 if (n < 0)
781 return NULL;
782 dp = ddebug_iter_first(iter);
783 while (dp != NULL && --n > 0)
784 dp = ddebug_iter_next(iter);
785 return dp;
786 }
787
788
789
790
791
792
793 static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
794 {
795 struct ddebug_iter *iter = m->private;
796 struct _ddebug *dp;
797
798 vpr_info("called m=%p p=%p *pos=%lld\n",
799 m, p, (unsigned long long)*pos);
800
801 if (p == SEQ_START_TOKEN)
802 dp = ddebug_iter_first(iter);
803 else
804 dp = ddebug_iter_next(iter);
805 ++*pos;
806 return dp;
807 }
808
809
810
811
812
813
814
815 static int ddebug_proc_show(struct seq_file *m, void *p)
816 {
817 struct ddebug_iter *iter = m->private;
818 struct _ddebug *dp = p;
819 char flagsbuf[10];
820
821 vpr_info("called m=%p p=%p\n", m, p);
822
823 if (p == SEQ_START_TOKEN) {
824 seq_puts(m,
825 "# filename:lineno [module]function flags format\n");
826 return 0;
827 }
828
829 seq_printf(m, "%s:%u [%s]%s =%s \"",
830 trim_prefix(dp->filename), dp->lineno,
831 iter->table->mod_name, dp->function,
832 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
833 seq_escape(m, dp->format, "\t\r\n\"");
834 seq_puts(m, "\"\n");
835
836 return 0;
837 }
838
839
840
841
842
843 static void ddebug_proc_stop(struct seq_file *m, void *p)
844 {
845 vpr_info("called m=%p p=%p\n", m, p);
846 mutex_unlock(&ddebug_lock);
847 }
848
849 static const struct seq_operations ddebug_proc_seqops = {
850 .start = ddebug_proc_start,
851 .next = ddebug_proc_next,
852 .show = ddebug_proc_show,
853 .stop = ddebug_proc_stop
854 };
855
856
857
858
859
860
861
862
863 static int ddebug_proc_open(struct inode *inode, struct file *file)
864 {
865 vpr_info("called\n");
866 return seq_open_private(file, &ddebug_proc_seqops,
867 sizeof(struct ddebug_iter));
868 }
869
870 static const struct file_operations ddebug_proc_fops = {
871 .owner = THIS_MODULE,
872 .open = ddebug_proc_open,
873 .read = seq_read,
874 .llseek = seq_lseek,
875 .release = seq_release_private,
876 .write = ddebug_proc_write
877 };
878
879
880
881
882
883 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
884 const char *name)
885 {
886 struct ddebug_table *dt;
887
888 dt = kzalloc(sizeof(*dt), GFP_KERNEL);
889 if (dt == NULL) {
890 pr_err("error adding module: %s\n", name);
891 return -ENOMEM;
892 }
893
894
895
896
897
898
899 dt->mod_name = name;
900 dt->num_ddebugs = n;
901 dt->ddebugs = tab;
902
903 mutex_lock(&ddebug_lock);
904 list_add_tail(&dt->link, &ddebug_tables);
905 mutex_unlock(&ddebug_lock);
906
907 vpr_info("%u debug prints in module %s\n", n, dt->mod_name);
908 return 0;
909 }
910
911
912 static int ddebug_dyndbg_param_cb(char *param, char *val,
913 const char *modname, int on_err)
914 {
915 char *sep;
916
917 sep = strchr(param, '.');
918 if (sep) {
919
920 *sep = '\0';
921 modname = param;
922 param = sep + 1;
923 }
924 if (strcmp(param, "dyndbg"))
925 return on_err;
926
927 ddebug_exec_queries((val ? val : "+p"), modname);
928
929 return 0;
930 }
931
932
933 static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
934 const char *unused, void *arg)
935 {
936 vpr_info("%s=\"%s\"\n", param, val);
937 return ddebug_dyndbg_param_cb(param, val, NULL, 0);
938 }
939
940
941
942
943
944
945 int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
946 {
947 vpr_info("module: %s %s=\"%s\"\n", module, param, val);
948 return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
949 }
950
951 static void ddebug_table_free(struct ddebug_table *dt)
952 {
953 list_del_init(&dt->link);
954 kfree(dt);
955 }
956
957
958
959
960
961 int ddebug_remove_module(const char *mod_name)
962 {
963 struct ddebug_table *dt, *nextdt;
964 int ret = -ENOENT;
965
966 vpr_info("removing module \"%s\"\n", mod_name);
967
968 mutex_lock(&ddebug_lock);
969 list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
970 if (dt->mod_name == mod_name) {
971 ddebug_table_free(dt);
972 ret = 0;
973 break;
974 }
975 }
976 mutex_unlock(&ddebug_lock);
977 return ret;
978 }
979
980 static void ddebug_remove_all_tables(void)
981 {
982 mutex_lock(&ddebug_lock);
983 while (!list_empty(&ddebug_tables)) {
984 struct ddebug_table *dt = list_entry(ddebug_tables.next,
985 struct ddebug_table,
986 link);
987 ddebug_table_free(dt);
988 }
989 mutex_unlock(&ddebug_lock);
990 }
991
992 static __initdata int ddebug_init_success;
993
994 static int __init dynamic_debug_init_debugfs(void)
995 {
996 struct dentry *dir;
997
998 if (!ddebug_init_success)
999 return -ENODEV;
1000
1001 dir = debugfs_create_dir("dynamic_debug", NULL);
1002 debugfs_create_file("control", 0644, dir, NULL, &ddebug_proc_fops);
1003
1004 return 0;
1005 }
1006
1007 static int __init dynamic_debug_init(void)
1008 {
1009 struct _ddebug *iter, *iter_start;
1010 const char *modname = NULL;
1011 char *cmdline;
1012 int ret = 0;
1013 int n = 0, entries = 0, modct = 0;
1014 int verbose_bytes = 0;
1015
1016 if (__start___verbose == __stop___verbose) {
1017 pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
1018 return 1;
1019 }
1020 iter = __start___verbose;
1021 modname = iter->modname;
1022 iter_start = iter;
1023 for (; iter < __stop___verbose; iter++) {
1024 entries++;
1025 verbose_bytes += strlen(iter->modname) + strlen(iter->function)
1026 + strlen(iter->filename) + strlen(iter->format);
1027
1028 if (strcmp(modname, iter->modname)) {
1029 modct++;
1030 ret = ddebug_add_module(iter_start, n, modname);
1031 if (ret)
1032 goto out_err;
1033 n = 0;
1034 modname = iter->modname;
1035 iter_start = iter;
1036 }
1037 n++;
1038 }
1039 ret = ddebug_add_module(iter_start, n, modname);
1040 if (ret)
1041 goto out_err;
1042
1043 ddebug_init_success = 1;
1044 vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
1045 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
1046 verbose_bytes + (int)(__stop___verbose - __start___verbose));
1047
1048
1049 if (ddebug_setup_string[0] != '\0') {
1050 pr_warn("ddebug_query param name is deprecated, change it to dyndbg\n");
1051 ret = ddebug_exec_queries(ddebug_setup_string, NULL);
1052 if (ret < 0)
1053 pr_warn("Invalid ddebug boot param %s\n",
1054 ddebug_setup_string);
1055 else
1056 pr_info("%d changes by ddebug_query\n", ret);
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066 cmdline = kstrdup(saved_command_line, GFP_KERNEL);
1067 parse_args("dyndbg params", cmdline, NULL,
1068 0, 0, 0, NULL, &ddebug_dyndbg_boot_param_cb);
1069 kfree(cmdline);
1070 return 0;
1071
1072 out_err:
1073 ddebug_remove_all_tables();
1074 return 0;
1075 }
1076
1077 early_initcall(dynamic_debug_init);
1078
1079
1080 fs_initcall(dynamic_debug_init_debugfs);