diff options
-rw-r--r-- | Documentation/dynamic-debug-howto.txt | 23 | ||||
-rw-r--r-- | lib/dynamic_debug.c | 73 |
2 files changed, 66 insertions, 30 deletions
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt index 378b5d1bf436..74e6c7782678 100644 --- a/Documentation/dynamic-debug-howto.txt +++ b/Documentation/dynamic-debug-howto.txt | |||
@@ -12,7 +12,7 @@ dynamically enabled per-callsite. | |||
12 | Dynamic debug has even more useful features: | 12 | Dynamic debug has even more useful features: |
13 | 13 | ||
14 | * Simple query language allows turning on and off debugging statements by | 14 | * Simple query language allows turning on and off debugging statements by |
15 | matching any combination of: | 15 | matching any combination of 0 or 1 of: |
16 | 16 | ||
17 | - source filename | 17 | - source filename |
18 | - function name | 18 | - function name |
@@ -79,31 +79,24 @@ Command Language Reference | |||
79 | ========================== | 79 | ========================== |
80 | 80 | ||
81 | At the lexical level, a command comprises a sequence of words separated | 81 | At the lexical level, a command comprises a sequence of words separated |
82 | by whitespace characters. Note that newlines are treated as word | 82 | by spaces or tabs. So these are all equivalent: |
83 | separators and do *not* end a command or allow multiple commands to | ||
84 | be done together. So these are all equivalent: | ||
85 | 83 | ||
86 | nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > | 84 | nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > |
87 | <debugfs>/dynamic_debug/control | 85 | <debugfs>/dynamic_debug/control |
88 | nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > | 86 | nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > |
89 | <debugfs>/dynamic_debug/control | 87 | <debugfs>/dynamic_debug/control |
90 | nullarbor:~ # echo -c 'file svcsock.c\nline 1603 +p' > | ||
91 | <debugfs>/dynamic_debug/control | ||
92 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > | 88 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > |
93 | <debugfs>/dynamic_debug/control | 89 | <debugfs>/dynamic_debug/control |
94 | 90 | ||
95 | Commands are bounded by a write() system call. If you want to do | 91 | Command submissions are bounded by a write() system call. |
96 | multiple commands you need to do a separate "echo" for each, like: | 92 | Multiple commands can be written together, separated by ';' or '\n'. |
97 | 93 | ||
98 | nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\ | 94 | ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \ |
99 | > echo 'file svcsock.c line 1563 +p' > /proc/dprintk | 95 | > <debugfs>/dynamic_debug/control |
100 | 96 | ||
101 | or even like: | 97 | If your query set is big, you can batch them too: |
102 | 98 | ||
103 | nullarbor:~ # ( | 99 | ~# cat query-batch-file > <debugfs>/dynamic_debug/control |
104 | > echo 'file svcsock.c line 1603 +p' ;\ | ||
105 | > echo 'file svcsock.c line 1563 +p' ;\ | ||
106 | > ) > /proc/dprintk | ||
107 | 100 | ||
108 | At the syntactical level, a command comprises a sequence of match | 101 | At the syntactical level, a command comprises a sequence of match |
109 | specifications, followed by a flags change specification. | 102 | specifications, followed by a flags change specification. |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 93fc5d500cd5..310c753cf83e 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
@@ -124,13 +124,13 @@ do { \ | |||
124 | } while (0) | 124 | } while (0) |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * Search the tables for _ddebug's which match the given | 127 | * Search the tables for _ddebug's which match the given `query' and |
128 | * `query' and apply the `flags' and `mask' to them. Tells | 128 | * apply the `flags' and `mask' to them. Returns number of matching |
129 | * the user which ddebug's were changed, or whether none | 129 | * callsites, normally the same as number of changes. If verbose, |
130 | * were matched. | 130 | * logs the changes. Takes ddebug_lock. |
131 | */ | 131 | */ |
132 | static void ddebug_change(const struct ddebug_query *query, | 132 | static int ddebug_change(const struct ddebug_query *query, |
133 | unsigned int flags, unsigned int mask) | 133 | unsigned int flags, unsigned int mask) |
134 | { | 134 | { |
135 | int i; | 135 | int i; |
136 | struct ddebug_table *dt; | 136 | struct ddebug_table *dt; |
@@ -192,6 +192,8 @@ static void ddebug_change(const struct ddebug_query *query, | |||
192 | 192 | ||
193 | if (!nfound && verbose) | 193 | if (!nfound && verbose) |
194 | pr_info("no matches for query\n"); | 194 | pr_info("no matches for query\n"); |
195 | |||
196 | return nfound; | ||
195 | } | 197 | } |
196 | 198 | ||
197 | /* | 199 | /* |
@@ -449,7 +451,7 @@ static int ddebug_exec_query(char *query_string) | |||
449 | unsigned int flags = 0, mask = 0; | 451 | unsigned int flags = 0, mask = 0; |
450 | struct ddebug_query query; | 452 | struct ddebug_query query; |
451 | #define MAXWORDS 9 | 453 | #define MAXWORDS 9 |
452 | int nwords; | 454 | int nwords, nfound; |
453 | char *words[MAXWORDS]; | 455 | char *words[MAXWORDS]; |
454 | 456 | ||
455 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); | 457 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); |
@@ -461,8 +463,47 @@ static int ddebug_exec_query(char *query_string) | |||
461 | return -EINVAL; | 463 | return -EINVAL; |
462 | 464 | ||
463 | /* actually go and implement the change */ | 465 | /* actually go and implement the change */ |
464 | ddebug_change(&query, flags, mask); | 466 | nfound = ddebug_change(&query, flags, mask); |
465 | return 0; | 467 | vpr_info_dq((&query), (nfound) ? "applied" : "no-match"); |
468 | |||
469 | return nfound; | ||
470 | } | ||
471 | |||
472 | /* handle multiple queries in query string, continue on error, return | ||
473 | last error or number of matching callsites. Module name is either | ||
474 | in param (for boot arg) or perhaps in query string. | ||
475 | */ | ||
476 | static int ddebug_exec_queries(char *query) | ||
477 | { | ||
478 | char *split; | ||
479 | int i, errs = 0, exitcode = 0, rc, nfound = 0; | ||
480 | |||
481 | for (i = 0; query; query = split) { | ||
482 | split = strpbrk(query, ";\n"); | ||
483 | if (split) | ||
484 | *split++ = '\0'; | ||
485 | |||
486 | query = skip_spaces(query); | ||
487 | if (!query || !*query || *query == '#') | ||
488 | continue; | ||
489 | |||
490 | if (verbose) | ||
491 | pr_info("query %d: \"%s\"\n", i, query); | ||
492 | |||
493 | rc = ddebug_exec_query(query); | ||
494 | if (rc < 0) { | ||
495 | errs++; | ||
496 | exitcode = rc; | ||
497 | } else | ||
498 | nfound += rc; | ||
499 | i++; | ||
500 | } | ||
501 | pr_info("processed %d queries, with %d matches, %d errs\n", | ||
502 | i, nfound, errs); | ||
503 | |||
504 | if (exitcode) | ||
505 | return exitcode; | ||
506 | return nfound; | ||
466 | } | 507 | } |
467 | 508 | ||
468 | #define PREFIX_SIZE 64 | 509 | #define PREFIX_SIZE 64 |
@@ -615,9 +656,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, | |||
615 | if (verbose) | 656 | if (verbose) |
616 | pr_info("read %d bytes from userspace\n", (int)len); | 657 | pr_info("read %d bytes from userspace\n", (int)len); |
617 | 658 | ||
618 | ret = ddebug_exec_query(tmpbuf); | 659 | ret = ddebug_exec_queries(tmpbuf); |
619 | kfree(tmpbuf); | 660 | kfree(tmpbuf); |
620 | if (ret) | 661 | if (ret < 0) |
621 | return ret; | 662 | return ret; |
622 | 663 | ||
623 | *offp += len; | 664 | *offp += len; |
@@ -927,13 +968,15 @@ static int __init dynamic_debug_init(void) | |||
927 | 968 | ||
928 | /* ddebug_query boot param got passed -> set it up */ | 969 | /* ddebug_query boot param got passed -> set it up */ |
929 | if (ddebug_setup_string[0] != '\0') { | 970 | if (ddebug_setup_string[0] != '\0') { |
930 | ret = ddebug_exec_query(ddebug_setup_string); | 971 | ret = ddebug_exec_queries(ddebug_setup_string); |
931 | if (ret) | 972 | if (ret < 0) |
932 | pr_warn("Invalid ddebug boot param %s", | 973 | pr_warn("Invalid ddebug boot param %s", |
933 | ddebug_setup_string); | 974 | ddebug_setup_string); |
934 | else | 975 | else |
935 | pr_info("ddebug initialized with string %s", | 976 | pr_info("%d changes by ddebug_query\n", ret); |
936 | ddebug_setup_string); | 977 | |
978 | /* keep tables even on ddebug_query parse error */ | ||
979 | ret = 0; | ||
937 | } | 980 | } |
938 | 981 | ||
939 | out_free: | 982 | out_free: |