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 const 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 = memdup_user_nul(ubuf, len);
661 if (IS_ERR(tmpbuf))
662 return PTR_ERR(tmpbuf);
663 vpr_info("read %d bytes from userspace\n", (int)len);
664
665 ret = ddebug_exec_queries(tmpbuf, NULL);
666 kfree(tmpbuf);
667 if (ret < 0)
668 return ret;
669
670 *offp += len;
671 return len;
672}
673
674
675
676
677
678
679static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
680{
681 if (list_empty(&ddebug_tables)) {
682 iter->table = NULL;
683 iter->idx = 0;
684 return NULL;
685 }
686 iter->table = list_entry(ddebug_tables.next,
687 struct ddebug_table, link);
688 iter->idx = 0;
689 return &iter->table->ddebugs[iter->idx];
690}
691
692
693
694
695
696
697
698static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
699{
700 if (iter->table == NULL)
701 return NULL;
702 if (++iter->idx == iter->table->num_ddebugs) {
703
704 iter->idx = 0;
705 if (list_is_last(&iter->table->link, &ddebug_tables)) {
706 iter->table = NULL;
707 return NULL;
708 }
709 iter->table = list_entry(iter->table->link.next,
710 struct ddebug_table, link);
711 }
712 return &iter->table->ddebugs[iter->idx];
713}
714
715
716
717
718
719
720static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
721{
722 struct ddebug_iter *iter = m->private;
723 struct _ddebug *dp;
724 int n = *pos;
725
726 vpr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
727
728 mutex_lock(&ddebug_lock);
729
730 if (!n)
731 return SEQ_START_TOKEN;
732 if (n < 0)
733 return NULL;
734 dp = ddebug_iter_first(iter);
735 while (dp != NULL && --n > 0)
736 dp = ddebug_iter_next(iter);
737 return dp;
738}
739
740
741
742
743
744
745static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
746{
747 struct ddebug_iter *iter = m->private;
748 struct _ddebug *dp;
749
750 vpr_info("called m=%p p=%p *pos=%lld\n",
751 m, p, (unsigned long long)*pos);
752
753 if (p == SEQ_START_TOKEN)
754 dp = ddebug_iter_first(iter);
755 else
756 dp = ddebug_iter_next(iter);
757 ++*pos;
758 return dp;
759}
760
761
762
763
764
765
766
767static int ddebug_proc_show(struct seq_file *m, void *p)
768{
769 struct ddebug_iter *iter = m->private;
770 struct _ddebug *dp = p;
771 char flagsbuf[10];
772
773 vpr_info("called m=%p p=%p\n", m, p);
774
775 if (p == SEQ_START_TOKEN) {
776 seq_puts(m,
777 "# filename:lineno [module]function flags format\n");
778 return 0;
779 }
780
781 seq_printf(m, "%s:%u [%s]%s =%s \"",
782 trim_prefix(dp->filename), dp->lineno,
783 iter->table->mod_name, dp->function,
784 ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
785 seq_escape(m, dp->format, "\t\r\n\"");
786 seq_puts(m, "\"\n");
787
788 return 0;
789}
790
791
792
793
794
795static void ddebug_proc_stop(struct seq_file *m, void *p)
796{
797 vpr_info("called m=%p p=%p\n", m, p);
798 mutex_unlock(&ddebug_lock);
799}
800
801static const struct seq_operations ddebug_proc_seqops = {
802 .start = ddebug_proc_start,
803 .next = ddebug_proc_next,
804 .show = ddebug_proc_show,
805 .stop = ddebug_proc_stop
806};
807
808
809
810
811
812
813
814
815static int ddebug_proc_open(struct inode *inode, struct file *file)
816{
817 vpr_info("called\n");
818 return seq_open_private(file, &ddebug_proc_seqops,
819 sizeof(struct ddebug_iter));
820}
821
822static const struct file_operations ddebug_proc_fops = {
823 .owner = THIS_MODULE,
824 .open = ddebug_proc_open,
825 .read = seq_read,
826 .llseek = seq_lseek,
827 .release = seq_release_private,
828 .write = ddebug_proc_write
829};
830
831
832
833
834
835int ddebug_add_module(struct _ddebug *tab, unsigned int n,
836 const char *name)
837{
838 struct ddebug_table *dt;
839 const char *new_name;
840
841 dt = kzalloc(sizeof(*dt), GFP_KERNEL);
842 if (dt == NULL)
843 return -ENOMEM;
844 new_name = kstrdup_const(name, GFP_KERNEL);
845 if (new_name == NULL) {
846 kfree(dt);
847 return -ENOMEM;
848 }
849 dt->mod_name = new_name;
850 dt->num_ddebugs = n;
851 dt->ddebugs = tab;
852
853 mutex_lock(&ddebug_lock);
854 list_add_tail(&dt->link, &ddebug_tables);
855 mutex_unlock(&ddebug_lock);
856
857 vpr_info("%u debug prints in module %s\n", n, dt->mod_name);
858 return 0;
859}
860EXPORT_SYMBOL_GPL(ddebug_add_module);
861
862
863static int ddebug_dyndbg_param_cb(char *param, char *val,
864 const char *modname, int on_err)
865{
866 char *sep;
867
868 sep = strchr(param, '.');
869 if (sep) {
870
871 *sep = '\0';
872 modname = param;
873 param = sep + 1;
874 }
875 if (strcmp(param, "dyndbg"))
876 return on_err;
877
878 ddebug_exec_queries((val ? val : "+p"), modname);
879
880 return 0;
881}
882
883
884static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
885 const char *unused, void *arg)
886{
887 vpr_info("%s=\"%s\"\n", param, val);
888 return ddebug_dyndbg_param_cb(param, val, NULL, 0);
889}
890
891
892
893
894
895
896int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
897{
898 vpr_info("module: %s %s=\"%s\"\n", module, param, val);
899 return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
900}
901
902static void ddebug_table_free(struct ddebug_table *dt)
903{
904 list_del_init(&dt->link);
905 kfree_const(dt->mod_name);
906 kfree(dt);
907}
908
909
910
911
912
913int ddebug_remove_module(const char *mod_name)
914{
915 struct ddebug_table *dt, *nextdt;
916 int ret = -ENOENT;
917
918 vpr_info("removing module \"%s\"\n", mod_name);
919
920 mutex_lock(&ddebug_lock);
921 list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
922 if (!strcmp(dt->mod_name, mod_name)) {
923 ddebug_table_free(dt);
924 ret = 0;
925 }
926 }
927 mutex_unlock(&ddebug_lock);
928 return ret;
929}
930EXPORT_SYMBOL_GPL(ddebug_remove_module);
931
932static void ddebug_remove_all_tables(void)
933{
934 mutex_lock(&ddebug_lock);
935 while (!list_empty(&ddebug_tables)) {
936 struct ddebug_table *dt = list_entry(ddebug_tables.next,
937 struct ddebug_table,
938 link);
939 ddebug_table_free(dt);
940 }
941 mutex_unlock(&ddebug_lock);
942}
943
944static __initdata int ddebug_init_success;
945
946static int __init dynamic_debug_init_debugfs(void)
947{
948 struct dentry *dir, *file;
949
950 if (!ddebug_init_success)
951 return -ENODEV;
952
953 dir = debugfs_create_dir("dynamic_debug", NULL);
954 if (!dir)
955 return -ENOMEM;
956 file = debugfs_create_file("control", 0644, dir, NULL,
957 &ddebug_proc_fops);
958 if (!file) {
959 debugfs_remove(dir);
960 return -ENOMEM;
961 }
962 return 0;
963}
964
965static int __init dynamic_debug_init(void)
966{
967 struct _ddebug *iter, *iter_start;
968 const char *modname = NULL;
969 char *cmdline;
970 int ret = 0;
971 int n = 0, entries = 0, modct = 0;
972 int verbose_bytes = 0;
973
974 if (__start___verbose == __stop___verbose) {
975 pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
976 return 1;
977 }
978 iter = __start___verbose;
979 modname = iter->modname;
980 iter_start = iter;
981 for (; iter < __stop___verbose; iter++) {
982 entries++;
983 verbose_bytes += strlen(iter->modname) + strlen(iter->function)
984 + strlen(iter->filename) + strlen(iter->format);
985
986 if (strcmp(modname, iter->modname)) {
987 modct++;
988 ret = ddebug_add_module(iter_start, n, modname);
989 if (ret)
990 goto out_err;
991 n = 0;
992 modname = iter->modname;
993 iter_start = iter;
994 }
995 n++;
996 }
997 ret = ddebug_add_module(iter_start, n, modname);
998 if (ret)
999 goto out_err;
1000
1001 ddebug_init_success = 1;
1002 vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
1003 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
1004 verbose_bytes + (int)(__stop___verbose - __start___verbose));
1005
1006
1007 if (ddebug_setup_string[0] != '\0') {
1008 pr_warn("ddebug_query param name is deprecated, change it to dyndbg\n");
1009 ret = ddebug_exec_queries(ddebug_setup_string, NULL);
1010 if (ret < 0)
1011 pr_warn("Invalid ddebug boot param %s\n",
1012 ddebug_setup_string);
1013 else
1014 pr_info("%d changes by ddebug_query\n", ret);
1015 }
1016
1017
1018
1019
1020
1021
1022
1023
1024 cmdline = kstrdup(saved_command_line, GFP_KERNEL);
1025 parse_args("dyndbg params", cmdline, NULL,
1026 0, 0, 0, NULL, &ddebug_dyndbg_boot_param_cb);
1027 kfree(cmdline);
1028 return 0;
1029
1030out_err:
1031 ddebug_remove_all_tables();
1032 return 0;
1033}
1034
1035early_initcall(dynamic_debug_init);
1036
1037
1038fs_initcall(dynamic_debug_init_debugfs);
1039