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