Blame view

lib/dynamic_debug.c 26.1 KB
e9d376f0f   Jason Baron   dynamic debug: co...
1
2
3
4
5
6
7
8
9
  /*
   * lib/dynamic_debug.c
   *
   * make pr_debug()/dev_dbg() calls runtime configurable based upon their
   * source module.
   *
   * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
   * By Greg Banks <gnb@melbourne.sgi.com>
   * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
10
   * Copyright (C) 2011 Bart Van Assche.  All Rights Reserved.
578b1e070   Du, Changbin   dynamic_debug: ad...
11
   * Copyright (C) 2013 Du, Changbin <changbin.du@gmail.com>
e9d376f0f   Jason Baron   dynamic debug: co...
12
   */
4ad275e5c   Joe Perches   dynamic_debug: Co...
13
  #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
e9d376f0f   Jason Baron   dynamic debug: co...
14
15
  #include <linux/kernel.h>
  #include <linux/module.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
16
17
18
  #include <linux/moduleparam.h>
  #include <linux/kallsyms.h>
  #include <linux/types.h>
e9d376f0f   Jason Baron   dynamic debug: co...
19
  #include <linux/mutex.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
20
  #include <linux/proc_fs.h>
e9d376f0f   Jason Baron   dynamic debug: co...
21
  #include <linux/seq_file.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
22
23
  #include <linux/list.h>
  #include <linux/sysctl.h>
e9d376f0f   Jason Baron   dynamic debug: co...
24
  #include <linux/ctype.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
25
  #include <linux/string.h>
578b1e070   Du, Changbin   dynamic_debug: ad...
26
  #include <linux/parser.h>
d338b1379   Andy Shevchenko   dynamic_debug: re...
27
  #include <linux/string_helpers.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
28
  #include <linux/uaccess.h>
e9d376f0f   Jason Baron   dynamic debug: co...
29
30
  #include <linux/dynamic_debug.h>
  #include <linux/debugfs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
32
  #include <linux/jump_label.h>
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
33
  #include <linux/hardirq.h>
e8d9792aa   Greg Kroah-Hartman   dynamic_debug: ad...
34
  #include <linux/sched.h>
fef15d2f3   Greg Kroah-Hartman   Revert "dynamic_d...
35
  #include <linux/device.h>
ffa10cb47   Jason Baron   dynamic_debug: ma...
36
  #include <linux/netdevice.h>
e9d376f0f   Jason Baron   dynamic debug: co...
37

923abb9d7   Gal Pressman   RDMA/core: Introd...
38
  #include <rdma/ib_verbs.h>
e9d376f0f   Jason Baron   dynamic debug: co...
39
40
  extern struct _ddebug __start___verbose[];
  extern struct _ddebug __stop___verbose[];
e9d376f0f   Jason Baron   dynamic debug: co...
41
42
  struct ddebug_table {
  	struct list_head link;
3e406b1d7   Rasmus Villemoes   lib/dynamic_debug...
43
  	const char *mod_name;
e9d376f0f   Jason Baron   dynamic debug: co...
44
  	unsigned int num_ddebugs;
e9d376f0f   Jason Baron   dynamic debug: co...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  	struct _ddebug *ddebugs;
  };
  
  struct ddebug_query {
  	const char *filename;
  	const char *module;
  	const char *function;
  	const char *format;
  	unsigned int first_lineno, last_lineno;
  };
  
  struct ddebug_iter {
  	struct ddebug_table *table;
  	unsigned int idx;
  };
  
  static DEFINE_MUTEX(ddebug_lock);
  static LIST_HEAD(ddebug_tables);
f657fd21e   Joe Perches   dynamic_debug: Fi...
63
  static int verbose;
74df138d5   Jim Cromie   dynamic_debug: ch...
64
  module_param(verbose, int, 0644);
e9d376f0f   Jason Baron   dynamic debug: co...
65

2b6783191   Jim Cromie   dynamic_debug: ad...
66
67
68
69
70
71
72
73
74
75
  /* Return the path relative to source root */
  static inline const char *trim_prefix(const char *path)
  {
  	int skip = strlen(__FILE__) - strlen("lib/dynamic_debug.c");
  
  	if (strncmp(path, __FILE__, skip))
  		skip = 0; /* prefix mismatch, don't skip */
  
  	return path + skip;
  }
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
76
77
78
79
80
81
  static struct { unsigned flag:8; char opt_char; } opt_array[] = {
  	{ _DPRINTK_FLAGS_PRINT, 'p' },
  	{ _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
  	{ _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
  	{ _DPRINTK_FLAGS_INCL_LINENO, 'l' },
  	{ _DPRINTK_FLAGS_INCL_TID, 't' },
5ca7d2a6c   Jim Cromie   dynamic_debug: de...
82
  	{ _DPRINTK_FLAGS_NONE, '_' },
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
83
  };
e9d376f0f   Jason Baron   dynamic debug: co...
84
85
86
87
88
  /* format a string into buf[] which describes the _ddebug's flags */
  static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
  				    size_t maxlen)
  {
  	char *p = buf;
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
89
  	int i;
e9d376f0f   Jason Baron   dynamic debug: co...
90

5ca7d2a6c   Jim Cromie   dynamic_debug: de...
91
  	BUG_ON(maxlen < 6);
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
92
93
94
  	for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
  		if (dp->flags & opt_array[i].flag)
  			*p++ = opt_array[i].opt_char;
e9d376f0f   Jason Baron   dynamic debug: co...
95
  	if (p == buf)
5ca7d2a6c   Jim Cromie   dynamic_debug: de...
96
  		*p++ = '_';
e9d376f0f   Jason Baron   dynamic debug: co...
97
98
99
100
  	*p = '\0';
  
  	return buf;
  }
f657fd21e   Joe Perches   dynamic_debug: Fi...
101
  #define vpr_info(fmt, ...)					\
b8ccd5dee   Jim Cromie   dynamic_debug: re...
102
  do {								\
f657fd21e   Joe Perches   dynamic_debug: Fi...
103
104
  	if (verbose)						\
  		pr_info(fmt, ##__VA_ARGS__);			\
574b3725e   Jim Cromie   dynamic_debug: fa...
105
  } while (0)
f657fd21e   Joe Perches   dynamic_debug: Fi...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
  {
  	/* trim any trailing newlines */
  	int fmtlen = 0;
  
  	if (query->format) {
  		fmtlen = strlen(query->format);
  		while (fmtlen && query->format[fmtlen - 1] == '
  ')
  			fmtlen--;
  	}
  
  	vpr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u
  ",
  		 msg,
  		 query->function ? query->function : "",
  		 query->filename ? query->filename : "",
  		 query->module ? query->module : "",
  		 fmtlen, query->format ? query->format : "",
  		 query->first_lineno, query->last_lineno);
  }
e9d376f0f   Jason Baron   dynamic debug: co...
127
  /*
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
128
129
130
131
   * Search the tables for _ddebug's which match the given `query' and
   * apply the `flags' and `mask' to them.  Returns number of matching
   * callsites, normally the same as number of changes.  If verbose,
   * logs the changes.  Takes ddebug_lock.
e9d376f0f   Jason Baron   dynamic debug: co...
132
   */
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
133
134
  static int ddebug_change(const struct ddebug_query *query,
  			unsigned int flags, unsigned int mask)
e9d376f0f   Jason Baron   dynamic debug: co...
135
136
137
138
139
  {
  	int i;
  	struct ddebug_table *dt;
  	unsigned int newflags;
  	unsigned int nfound = 0;
5ca7d2a6c   Jim Cromie   dynamic_debug: de...
140
  	char flagbuf[10];
e9d376f0f   Jason Baron   dynamic debug: co...
141
142
143
144
145
146
  
  	/* search for matching ddebugs */
  	mutex_lock(&ddebug_lock);
  	list_for_each_entry(dt, &ddebug_tables, link) {
  
  		/* match against the module name */
578b1e070   Du, Changbin   dynamic_debug: ad...
147
148
  		if (query->module &&
  		    !match_wildcard(query->module, dt->mod_name))
e9d376f0f   Jason Baron   dynamic debug: co...
149
  			continue;
f657fd21e   Joe Perches   dynamic_debug: Fi...
150
  		for (i = 0; i < dt->num_ddebugs; i++) {
e9d376f0f   Jason Baron   dynamic debug: co...
151
152
153
  			struct _ddebug *dp = &dt->ddebugs[i];
  
  			/* match against the source filename */
d6a238d25   Jim Cromie   dynamic_debug: dr...
154
  			if (query->filename &&
578b1e070   Du, Changbin   dynamic_debug: ad...
155
156
157
158
159
  			    !match_wildcard(query->filename, dp->filename) &&
  			    !match_wildcard(query->filename,
  					   kbasename(dp->filename)) &&
  			    !match_wildcard(query->filename,
  					   trim_prefix(dp->filename)))
e9d376f0f   Jason Baron   dynamic debug: co...
160
161
162
  				continue;
  
  			/* match against the function */
d6a238d25   Jim Cromie   dynamic_debug: dr...
163
  			if (query->function &&
578b1e070   Du, Changbin   dynamic_debug: ad...
164
  			    !match_wildcard(query->function, dp->function))
e9d376f0f   Jason Baron   dynamic debug: co...
165
166
167
  				continue;
  
  			/* match against the format */
d6a238d25   Jim Cromie   dynamic_debug: dr...
168
169
  			if (query->format &&
  			    !strstr(dp->format, query->format))
e9d376f0f   Jason Baron   dynamic debug: co...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  				continue;
  
  			/* match against the line number range */
  			if (query->first_lineno &&
  			    dp->lineno < query->first_lineno)
  				continue;
  			if (query->last_lineno &&
  			    dp->lineno > query->last_lineno)
  				continue;
  
  			nfound++;
  
  			newflags = (dp->flags & mask) | flags;
  			if (newflags == dp->flags)
  				continue;
e9666d10a   Masahiro Yamada   jump_label: move ...
185
  #ifdef CONFIG_JUMP_LABEL
9049fc745   Jason Baron   dynamic_debug: ad...
186
187
188
189
190
191
  			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
  				if (!(flags & _DPRINTK_FLAGS_PRINT))
  					static_branch_disable(&dp->key.dd_key_true);
  			} else if (flags & _DPRINTK_FLAGS_PRINT)
  				static_branch_enable(&dp->key.dd_key_true);
  #endif
e9d376f0f   Jason Baron   dynamic debug: co...
192
  			dp->flags = newflags;
b8ccd5dee   Jim Cromie   dynamic_debug: re...
193
194
  			vpr_info("changed %s:%d [%s]%s =%s
  ",
f657fd21e   Joe Perches   dynamic_debug: Fi...
195
196
197
198
  				 trim_prefix(dp->filename), dp->lineno,
  				 dt->mod_name, dp->function,
  				 ddebug_describe_flags(dp, flagbuf,
  						       sizeof(flagbuf)));
e9d376f0f   Jason Baron   dynamic debug: co...
199
200
201
202
203
  		}
  	}
  	mutex_unlock(&ddebug_lock);
  
  	if (!nfound && verbose)
4ad275e5c   Joe Perches   dynamic_debug: Co...
204
205
  		pr_info("no matches for query
  ");
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
206
207
  
  	return nfound;
e9d376f0f   Jason Baron   dynamic debug: co...
208
209
210
  }
  
  /*
e9d376f0f   Jason Baron   dynamic debug: co...
211
   * Split the buffer `buf' into space-separated words.
9898abb3d   Greg Banks   Dynamic debug: al...
212
213
214
   * Handles simple " and ' quoting, i.e. without nested,
   * embedded or escaped \".  Return the number of words
   * or <0 on error.
e9d376f0f   Jason Baron   dynamic debug: co...
215
216
217
218
   */
  static int ddebug_tokenize(char *buf, char *words[], int maxwords)
  {
  	int nwords = 0;
9898abb3d   Greg Banks   Dynamic debug: al...
219
220
221
222
  	while (*buf) {
  		char *end;
  
  		/* Skip leading whitespace */
e7d2860b6   André Goddard Rosa   tree-wide: conver...
223
  		buf = skip_spaces(buf);
9898abb3d   Greg Banks   Dynamic debug: al...
224
225
  		if (!*buf)
  			break;	/* oh, it was trailing whitespace */
8bd6026e8   Jim Cromie   dynamic_debug: ch...
226
227
  		if (*buf == '#')
  			break;	/* token starts comment, skip rest of line */
9898abb3d   Greg Banks   Dynamic debug: al...
228

07100be7e   Jim Cromie   dynamic_debug: fi...
229
  		/* find `end' of word, whitespace separated or quoted */
9898abb3d   Greg Banks   Dynamic debug: al...
230
231
  		if (*buf == '"' || *buf == '\'') {
  			int quote = *buf++;
f657fd21e   Joe Perches   dynamic_debug: Fi...
232
  			for (end = buf; *end && *end != quote; end++)
9898abb3d   Greg Banks   Dynamic debug: al...
233
  				;
18c216c53   Jim Cromie   dynamic_debug: ad...
234
235
236
  			if (!*end) {
  				pr_err("unclosed quote: %s
  ", buf);
9898abb3d   Greg Banks   Dynamic debug: al...
237
  				return -EINVAL;	/* unclosed quote */
18c216c53   Jim Cromie   dynamic_debug: ad...
238
  			}
9898abb3d   Greg Banks   Dynamic debug: al...
239
  		} else {
f657fd21e   Joe Perches   dynamic_debug: Fi...
240
  			for (end = buf; *end && !isspace(*end); end++)
9898abb3d   Greg Banks   Dynamic debug: al...
241
242
243
  				;
  			BUG_ON(end == buf);
  		}
9898abb3d   Greg Banks   Dynamic debug: al...
244

07100be7e   Jim Cromie   dynamic_debug: fi...
245
  		/* `buf' is start of word, `end' is one past its end */
18c216c53   Jim Cromie   dynamic_debug: ad...
246
247
248
  		if (nwords == maxwords) {
  			pr_err("too many words, legal max <=%d
  ", maxwords);
9898abb3d   Greg Banks   Dynamic debug: al...
249
  			return -EINVAL;	/* ran out of words[] before bytes */
18c216c53   Jim Cromie   dynamic_debug: ad...
250
  		}
9898abb3d   Greg Banks   Dynamic debug: al...
251
252
253
254
255
  		if (*end)
  			*end++ = '\0';	/* terminate the word */
  		words[nwords++] = buf;
  		buf = end;
  	}
e9d376f0f   Jason Baron   dynamic debug: co...
256
257
258
  
  	if (verbose) {
  		int i;
4ad275e5c   Joe Perches   dynamic_debug: Co...
259
  		pr_info("split into words:");
f657fd21e   Joe Perches   dynamic_debug: Fi...
260
  		for (i = 0; i < nwords; i++)
4ad275e5c   Joe Perches   dynamic_debug: Co...
261
262
263
  			pr_cont(" \"%s\"", words[i]);
  		pr_cont("
  ");
e9d376f0f   Jason Baron   dynamic debug: co...
264
265
266
267
268
269
270
271
272
273
274
275
  	}
  
  	return nwords;
  }
  
  /*
   * Parse a single line number.  Note that the empty string ""
   * is treated as a special case and converted to zero, which
   * is later treated as a "don't care" value.
   */
  static inline int parse_lineno(const char *str, unsigned int *val)
  {
e9d376f0f   Jason Baron   dynamic debug: co...
276
277
278
279
280
  	BUG_ON(str == NULL);
  	if (*str == '\0') {
  		*val = 0;
  		return 0;
  	}
4592599af   Andrey Ryabinin   dynamic_debug: re...
281
  	if (kstrtouint(str, 10, val) < 0) {
18c216c53   Jim Cromie   dynamic_debug: ad...
282
283
284
285
286
  		pr_err("bad line-number: %s
  ", str);
  		return -EINVAL;
  	}
  	return 0;
e9d376f0f   Jason Baron   dynamic debug: co...
287
  }
820874c75   Jim Cromie   dynamic_debug: ti...
288
289
290
291
292
293
  static int check_set(const char **dest, char *src, char *name)
  {
  	int rc = 0;
  
  	if (*dest) {
  		rc = -EINVAL;
f657fd21e   Joe Perches   dynamic_debug: Fi...
294
295
296
  		pr_err("match-spec:%s val:%s overridden by %s
  ",
  		       name, *dest, src);
820874c75   Jim Cromie   dynamic_debug: ti...
297
298
299
300
  	}
  	*dest = src;
  	return rc;
  }
e9d376f0f   Jason Baron   dynamic debug: co...
301
302
303
304
305
306
307
308
309
310
311
  /*
   * Parse words[] as a ddebug query specification, which is a series
   * of (keyword, value) pairs chosen from these possibilities:
   *
   * func <function-name>
   * file <full-pathname>
   * file <base-filename>
   * module <module-name>
   * format <escaped-string-to-find-in-format>
   * line <lineno>
   * line <first-lineno>-<last-lineno> // where either may be empty
820874c75   Jim Cromie   dynamic_debug: ti...
312
313
314
   *
   * Only 1 of each type is allowed.
   * Returns 0 on success, <0 on error.
e9d376f0f   Jason Baron   dynamic debug: co...
315
316
   */
  static int ddebug_parse_query(char *words[], int nwords,
8e59b5cfb   Jim Cromie   dynamic_debug: ad...
317
  			struct ddebug_query *query, const char *modname)
e9d376f0f   Jason Baron   dynamic debug: co...
318
319
  {
  	unsigned int i;
bd8c154a6   jbaron@akamai.com   dynamic debug: li...
320
  	int rc = 0;
e9d376f0f   Jason Baron   dynamic debug: co...
321
322
  
  	/* check we have an even number of words */
18c216c53   Jim Cromie   dynamic_debug: ad...
323
324
325
  	if (nwords % 2 != 0) {
  		pr_err("expecting pairs of match-spec <value>
  ");
e9d376f0f   Jason Baron   dynamic debug: co...
326
  		return -EINVAL;
18c216c53   Jim Cromie   dynamic_debug: ad...
327
  	}
e9d376f0f   Jason Baron   dynamic debug: co...
328
  	memset(query, 0, sizeof(*query));
8e59b5cfb   Jim Cromie   dynamic_debug: ad...
329
330
331
  	if (modname)
  		/* support $modname.dyndbg=<multiple queries> */
  		query->module = modname;
f657fd21e   Joe Perches   dynamic_debug: Fi...
332
333
  	for (i = 0; i < nwords; i += 2) {
  		if (!strcmp(words[i], "func")) {
820874c75   Jim Cromie   dynamic_debug: ti...
334
  			rc = check_set(&query->function, words[i+1], "func");
f657fd21e   Joe Perches   dynamic_debug: Fi...
335
  		} else if (!strcmp(words[i], "file")) {
820874c75   Jim Cromie   dynamic_debug: ti...
336
  			rc = check_set(&query->filename, words[i+1], "file");
f657fd21e   Joe Perches   dynamic_debug: Fi...
337
  		} else if (!strcmp(words[i], "module")) {
820874c75   Jim Cromie   dynamic_debug: ti...
338
  			rc = check_set(&query->module, words[i+1], "module");
f657fd21e   Joe Perches   dynamic_debug: Fi...
339
  		} else if (!strcmp(words[i], "format")) {
d338b1379   Andy Shevchenko   dynamic_debug: re...
340
341
342
343
  			string_unescape_inplace(words[i+1], UNESCAPE_SPACE |
  							    UNESCAPE_OCTAL |
  							    UNESCAPE_SPECIAL);
  			rc = check_set(&query->format, words[i+1], "format");
f657fd21e   Joe Perches   dynamic_debug: Fi...
344
  		} else if (!strcmp(words[i], "line")) {
e9d376f0f   Jason Baron   dynamic debug: co...
345
346
  			char *first = words[i+1];
  			char *last = strchr(first, '-');
820874c75   Jim Cromie   dynamic_debug: ti...
347
  			if (query->first_lineno || query->last_lineno) {
18c216c53   Jim Cromie   dynamic_debug: ad...
348
349
  				pr_err("match-spec: line used 2x
  ");
820874c75   Jim Cromie   dynamic_debug: ti...
350
351
  				return -EINVAL;
  			}
e9d376f0f   Jason Baron   dynamic debug: co...
352
353
  			if (last)
  				*last++ = '\0';
d9e133e6f   Andrey Ryabinin   dynamic_debug: re...
354
  			if (parse_lineno(first, &query->first_lineno) < 0)
e9d376f0f   Jason Baron   dynamic debug: co...
355
  				return -EINVAL;
820874c75   Jim Cromie   dynamic_debug: ti...
356
  			if (last) {
e9d376f0f   Jason Baron   dynamic debug: co...
357
  				/* range <first>-<last> */
3ace678fd   Andrey Ryabinin   dynamic_debug: fi...
358
359
  				if (parse_lineno(last, &query->last_lineno) < 0)
  					return -EINVAL;
1f3c790bd   Randy Dunlap   dynamic-debug-how...
360
361
362
  				/* special case for last lineno not specified */
  				if (query->last_lineno == 0)
  					query->last_lineno = UINT_MAX;
3ace678fd   Andrey Ryabinin   dynamic_debug: fi...
363
  				if (query->last_lineno < query->first_lineno) {
18c216c53   Jim Cromie   dynamic_debug: ad...
364
365
366
367
  					pr_err("last-line:%d < 1st-line:%d
  ",
  						query->last_lineno,
  						query->first_lineno);
e9d376f0f   Jason Baron   dynamic debug: co...
368
  					return -EINVAL;
820874c75   Jim Cromie   dynamic_debug: ti...
369
  				}
e9d376f0f   Jason Baron   dynamic debug: co...
370
371
372
373
  			} else {
  				query->last_lineno = query->first_lineno;
  			}
  		} else {
ae27f86a2   Jim Cromie   dynamic_debug: pr...
374
375
  			pr_err("unknown keyword \"%s\"
  ", words[i]);
e9d376f0f   Jason Baron   dynamic debug: co...
376
377
  			return -EINVAL;
  		}
820874c75   Jim Cromie   dynamic_debug: ti...
378
379
  		if (rc)
  			return rc;
e9d376f0f   Jason Baron   dynamic debug: co...
380
  	}
574b3725e   Jim Cromie   dynamic_debug: fa...
381
  	vpr_info_dq(query, "parsed");
e9d376f0f   Jason Baron   dynamic debug: co...
382
383
384
385
386
387
388
389
390
391
392
393
394
  	return 0;
  }
  
  /*
   * Parse `str' as a flags specification, format [-+=][p]+.
   * Sets up *maskp and *flagsp to be used when changing the
   * flags fields of matched _ddebug's.  Returns 0 on success
   * or <0 on error.
   */
  static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
  			       unsigned int *maskp)
  {
  	unsigned flags = 0;
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
395
  	int op = '=', i;
e9d376f0f   Jason Baron   dynamic debug: co...
396
397
398
399
400
401
402
403
  
  	switch (*str) {
  	case '+':
  	case '-':
  	case '=':
  		op = *str++;
  		break;
  	default:
18c216c53   Jim Cromie   dynamic_debug: ad...
404
405
  		pr_err("bad flag-op %c, at start of %s
  ", *str, str);
e9d376f0f   Jason Baron   dynamic debug: co...
406
407
  		return -EINVAL;
  	}
b8ccd5dee   Jim Cromie   dynamic_debug: re...
408
409
  	vpr_info("op='%c'
  ", op);
e9d376f0f   Jason Baron   dynamic debug: co...
410

f657fd21e   Joe Perches   dynamic_debug: Fi...
411
  	for (; *str ; ++str) {
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
412
413
414
415
416
  		for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
  			if (*str == opt_array[i].opt_char) {
  				flags |= opt_array[i].flag;
  				break;
  			}
e9d376f0f   Jason Baron   dynamic debug: co...
417
  		}
18c216c53   Jim Cromie   dynamic_debug: ad...
418
419
420
  		if (i < 0) {
  			pr_err("unknown flag '%c' in \"%s\"
  ", *str, str);
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
421
  			return -EINVAL;
18c216c53   Jim Cromie   dynamic_debug: ad...
422
  		}
e9d376f0f   Jason Baron   dynamic debug: co...
423
  	}
b8ccd5dee   Jim Cromie   dynamic_debug: re...
424
425
  	vpr_info("flags=0x%x
  ", flags);
e9d376f0f   Jason Baron   dynamic debug: co...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  
  	/* calculate final *flagsp, *maskp according to mask and op */
  	switch (op) {
  	case '=':
  		*maskp = 0;
  		*flagsp = flags;
  		break;
  	case '+':
  		*maskp = ~0U;
  		*flagsp = flags;
  		break;
  	case '-':
  		*maskp = ~flags;
  		*flagsp = 0;
  		break;
  	}
b8ccd5dee   Jim Cromie   dynamic_debug: re...
442
443
  	vpr_info("*flagsp=0x%x *maskp=0x%x
  ", *flagsp, *maskp);
e9d376f0f   Jason Baron   dynamic debug: co...
444
445
  	return 0;
  }
8e59b5cfb   Jim Cromie   dynamic_debug: ad...
446
  static int ddebug_exec_query(char *query_string, const char *modname)
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
447
448
449
450
  {
  	unsigned int flags = 0, mask = 0;
  	struct ddebug_query query;
  #define MAXWORDS 9
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
451
  	int nwords, nfound;
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
452
453
454
  	char *words[MAXWORDS];
  
  	nwords = ddebug_tokenize(query_string, words, MAXWORDS);
18c216c53   Jim Cromie   dynamic_debug: ad...
455
456
457
  	if (nwords <= 0) {
  		pr_err("tokenize failed
  ");
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
458
  		return -EINVAL;
18c216c53   Jim Cromie   dynamic_debug: ad...
459
460
461
462
463
  	}
  	/* check flags 1st (last arg) so query is pairs of spec,val */
  	if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) {
  		pr_err("flags parse failed
  ");
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
464
  		return -EINVAL;
18c216c53   Jim Cromie   dynamic_debug: ad...
465
466
467
468
  	}
  	if (ddebug_parse_query(words, nwords-1, &query, modname)) {
  		pr_err("query parse failed
  ");
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
469
  		return -EINVAL;
18c216c53   Jim Cromie   dynamic_debug: ad...
470
  	}
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
471
  	/* actually go and implement the change */
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
472
  	nfound = ddebug_change(&query, flags, mask);
f657fd21e   Joe Perches   dynamic_debug: Fi...
473
  	vpr_info_dq(&query, nfound ? "applied" : "no-match");
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
474
475
476
477
478
479
480
481
  
  	return nfound;
  }
  
  /* handle multiple queries in query string, continue on error, return
     last error or number of matching callsites.  Module name is either
     in param (for boot arg) or perhaps in query string.
  */
8e59b5cfb   Jim Cromie   dynamic_debug: ad...
482
  static int ddebug_exec_queries(char *query, const char *modname)
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
483
484
485
486
487
488
489
490
491
492
493
494
495
  {
  	char *split;
  	int i, errs = 0, exitcode = 0, rc, nfound = 0;
  
  	for (i = 0; query; query = split) {
  		split = strpbrk(query, ";
  ");
  		if (split)
  			*split++ = '\0';
  
  		query = skip_spaces(query);
  		if (!query || !*query || *query == '#')
  			continue;
b8ccd5dee   Jim Cromie   dynamic_debug: re...
496
497
  		vpr_info("query %d: \"%s\"
  ", i, query);
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
498

8e59b5cfb   Jim Cromie   dynamic_debug: ad...
499
  		rc = ddebug_exec_query(query, modname);
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
500
501
502
  		if (rc < 0) {
  			errs++;
  			exitcode = rc;
f657fd21e   Joe Perches   dynamic_debug: Fi...
503
  		} else {
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
504
  			nfound += rc;
f657fd21e   Joe Perches   dynamic_debug: Fi...
505
  		}
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
506
507
  		i++;
  	}
b8ccd5dee   Jim Cromie   dynamic_debug: re...
508
509
  	vpr_info("processed %d queries, with %d matches, %d errs
  ",
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
510
511
512
513
514
  		 i, nfound, errs);
  
  	if (exitcode)
  		return exitcode;
  	return nfound;
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
515
  }
431625dac   Jason Baron   dynamic_debug: us...
516
517
518
519
520
521
522
523
524
525
  #define PREFIX_SIZE 64
  
  static int remaining(int wrote)
  {
  	if (PREFIX_SIZE - wrote > 0)
  		return PREFIX_SIZE - wrote;
  	return 0;
  }
  
  static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
526
  {
431625dac   Jason Baron   dynamic_debug: us...
527
528
  	int pos_after_tid;
  	int pos = 0;
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
529

798efc60e   Joe Perches   dev_dbg/dynamic_d...
530
  	*buf = '\0';
431625dac   Jason Baron   dynamic_debug: us...
531
  	if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
532
  		if (in_interrupt())
798efc60e   Joe Perches   dev_dbg/dynamic_d...
533
  			pos += snprintf(buf + pos, remaining(pos), "<intr> ");
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
534
  		else
431625dac   Jason Baron   dynamic_debug: us...
535
  			pos += snprintf(buf + pos, remaining(pos), "[%d] ",
798efc60e   Joe Perches   dev_dbg/dynamic_d...
536
  					task_pid_vnr(current));
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
537
  	}
431625dac   Jason Baron   dynamic_debug: us...
538
539
540
  	pos_after_tid = pos;
  	if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
  		pos += snprintf(buf + pos, remaining(pos), "%s:",
798efc60e   Joe Perches   dev_dbg/dynamic_d...
541
  				desc->modname);
431625dac   Jason Baron   dynamic_debug: us...
542
543
  	if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
  		pos += snprintf(buf + pos, remaining(pos), "%s:",
798efc60e   Joe Perches   dev_dbg/dynamic_d...
544
  				desc->function);
431625dac   Jason Baron   dynamic_debug: us...
545
  	if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
07100be7e   Jim Cromie   dynamic_debug: fi...
546
  		pos += snprintf(buf + pos, remaining(pos), "%d:",
798efc60e   Joe Perches   dev_dbg/dynamic_d...
547
  				desc->lineno);
431625dac   Jason Baron   dynamic_debug: us...
548
549
550
551
  	if (pos - pos_after_tid)
  		pos += snprintf(buf + pos, remaining(pos), " ");
  	if (pos >= PREFIX_SIZE)
  		buf[PREFIX_SIZE - 1] = '\0';
6c2140ee0   Joe Perches   dynamic_debug: Co...
552

431625dac   Jason Baron   dynamic_debug: us...
553
  	return buf;
6c2140ee0   Joe Perches   dynamic_debug: Co...
554
  }
906d20153   Joe Perches   dynamic_debug: ch...
555
  void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
556
557
  {
  	va_list args;
431625dac   Jason Baron   dynamic_debug: us...
558
559
  	struct va_format vaf;
  	char buf[PREFIX_SIZE];
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
560
561
562
563
564
  
  	BUG_ON(!descriptor);
  	BUG_ON(!fmt);
  
  	va_start(args, fmt);
798efc60e   Joe Perches   dev_dbg/dynamic_d...
565

431625dac   Jason Baron   dynamic_debug: us...
566
567
  	vaf.fmt = fmt;
  	vaf.va = &args;
798efc60e   Joe Perches   dev_dbg/dynamic_d...
568

906d20153   Joe Perches   dynamic_debug: ch...
569
  	printk(KERN_DEBUG "%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf);
798efc60e   Joe Perches   dev_dbg/dynamic_d...
570

8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
571
  	va_end(args);
8ba6ebf58   Bart Van Assche   Dynamic debug: Ad...
572
573
  }
  EXPORT_SYMBOL(__dynamic_pr_debug);
906d20153   Joe Perches   dynamic_debug: ch...
574
  void __dynamic_dev_dbg(struct _ddebug *descriptor,
cbc466355   Joe Perches   dynamic_debug: Ad...
575
576
577
578
  		      const struct device *dev, const char *fmt, ...)
  {
  	struct va_format vaf;
  	va_list args;
cbc466355   Joe Perches   dynamic_debug: Ad...
579
580
581
582
583
  
  	BUG_ON(!descriptor);
  	BUG_ON(!fmt);
  
  	va_start(args, fmt);
798efc60e   Joe Perches   dev_dbg/dynamic_d...
584

cbc466355   Joe Perches   dynamic_debug: Ad...
585
586
  	vaf.fmt = fmt;
  	vaf.va = &args;
798efc60e   Joe Perches   dev_dbg/dynamic_d...
587
588
  
  	if (!dev) {
906d20153   Joe Perches   dynamic_debug: ch...
589
  		printk(KERN_DEBUG "(NULL device *): %pV", &vaf);
798efc60e   Joe Perches   dev_dbg/dynamic_d...
590
591
  	} else {
  		char buf[PREFIX_SIZE];
798efc60e   Joe Perches   dev_dbg/dynamic_d...
592

a39d4a857   Joe Perches   printk: add and u...
593
  		dev_printk_emit(LOGLEVEL_DEBUG, dev, "%s%s %s: %pV",
906d20153   Joe Perches   dynamic_debug: ch...
594
595
596
  				dynamic_emit_prefix(descriptor, buf),
  				dev_driver_string(dev), dev_name(dev),
  				&vaf);
798efc60e   Joe Perches   dev_dbg/dynamic_d...
597
  	}
cbc466355   Joe Perches   dynamic_debug: Ad...
598
  	va_end(args);
cbc466355   Joe Perches   dynamic_debug: Ad...
599
600
  }
  EXPORT_SYMBOL(__dynamic_dev_dbg);
0feefd978   Jason Baron   dynamic_debug: fi...
601
  #ifdef CONFIG_NET
906d20153   Joe Perches   dynamic_debug: ch...
602
603
  void __dynamic_netdev_dbg(struct _ddebug *descriptor,
  			  const struct net_device *dev, const char *fmt, ...)
ffa10cb47   Jason Baron   dynamic_debug: ma...
604
605
606
  {
  	struct va_format vaf;
  	va_list args;
ffa10cb47   Jason Baron   dynamic_debug: ma...
607
608
609
610
611
  
  	BUG_ON(!descriptor);
  	BUG_ON(!fmt);
  
  	va_start(args, fmt);
b004ff497   Joe Perches   netdev_printk/dyn...
612

ffa10cb47   Jason Baron   dynamic_debug: ma...
613
614
  	vaf.fmt = fmt;
  	vaf.va = &args;
b004ff497   Joe Perches   netdev_printk/dyn...
615
616
617
  
  	if (dev && dev->dev.parent) {
  		char buf[PREFIX_SIZE];
666f355f3   Joe Perches   device and dynami...
618

a39d4a857   Joe Perches   printk: add and u...
619
  		dev_printk_emit(LOGLEVEL_DEBUG, dev->dev.parent,
906d20153   Joe Perches   dynamic_debug: ch...
620
621
622
623
624
625
  				"%s%s %s %s%s: %pV",
  				dynamic_emit_prefix(descriptor, buf),
  				dev_driver_string(dev->dev.parent),
  				dev_name(dev->dev.parent),
  				netdev_name(dev), netdev_reg_state(dev),
  				&vaf);
b004ff497   Joe Perches   netdev_printk/dyn...
626
  	} else if (dev) {
906d20153   Joe Perches   dynamic_debug: ch...
627
628
  		printk(KERN_DEBUG "%s%s: %pV", netdev_name(dev),
  		       netdev_reg_state(dev), &vaf);
b004ff497   Joe Perches   netdev_printk/dyn...
629
  	} else {
906d20153   Joe Perches   dynamic_debug: ch...
630
  		printk(KERN_DEBUG "(NULL net_device): %pV", &vaf);
b004ff497   Joe Perches   netdev_printk/dyn...
631
  	}
ffa10cb47   Jason Baron   dynamic_debug: ma...
632
  	va_end(args);
ffa10cb47   Jason Baron   dynamic_debug: ma...
633
634
  }
  EXPORT_SYMBOL(__dynamic_netdev_dbg);
0feefd978   Jason Baron   dynamic_debug: fi...
635
  #endif
923abb9d7   Gal Pressman   RDMA/core: Introd...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
  #if IS_ENABLED(CONFIG_INFINIBAND)
  
  void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  			 const struct ib_device *ibdev, const char *fmt, ...)
  {
  	struct va_format vaf;
  	va_list args;
  
  	va_start(args, fmt);
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	if (ibdev && ibdev->dev.parent) {
  		char buf[PREFIX_SIZE];
  
  		dev_printk_emit(LOGLEVEL_DEBUG, ibdev->dev.parent,
  				"%s%s %s %s: %pV",
  				dynamic_emit_prefix(descriptor, buf),
  				dev_driver_string(ibdev->dev.parent),
  				dev_name(ibdev->dev.parent),
  				dev_name(&ibdev->dev),
  				&vaf);
  	} else if (ibdev) {
  		printk(KERN_DEBUG "%s: %pV", dev_name(&ibdev->dev), &vaf);
  	} else {
  		printk(KERN_DEBUG "(NULL ib_device): %pV", &vaf);
  	}
  
  	va_end(args);
  }
  EXPORT_SYMBOL(__dynamic_ibdev_dbg);
  
  #endif
bc757f6f5   Jim Cromie   dynamic_debug: re...
670
671
  #define DDEBUG_STRING_SIZE 1024
  static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE];
a648ec05b   Thomas Renninger   Dynamic Debug: In...
672
673
  static __init int ddebug_setup_query(char *str)
  {
bc757f6f5   Jim Cromie   dynamic_debug: re...
674
  	if (strlen(str) >= DDEBUG_STRING_SIZE) {
4ad275e5c   Joe Perches   dynamic_debug: Co...
675
676
  		pr_warn("ddebug boot param string too large
  ");
a648ec05b   Thomas Renninger   Dynamic Debug: In...
677
678
  		return 0;
  	}
bc757f6f5   Jim Cromie   dynamic_debug: re...
679
  	strlcpy(ddebug_setup_string, str, DDEBUG_STRING_SIZE);
a648ec05b   Thomas Renninger   Dynamic Debug: In...
680
681
682
683
  	return 1;
  }
  
  __setup("ddebug_query=", ddebug_setup_query);
e9d376f0f   Jason Baron   dynamic debug: co...
684
  /*
231821d4c   Masatake YAMATO   dynamic_debug: fi...
685
   * File_ops->write method for <debugfs>/dynamic_debug/control.  Gathers the
e9d376f0f   Jason Baron   dynamic debug: co...
686
687
   * command text from userspace, parses and executes it.
   */
7281491c5   Jim Cromie   dynamic_debug: en...
688
  #define USER_BUF_PAGE 4096
e9d376f0f   Jason Baron   dynamic debug: co...
689
690
691
  static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
  				  size_t len, loff_t *offp)
  {
7281491c5   Jim Cromie   dynamic_debug: en...
692
  	char *tmpbuf;
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
693
  	int ret;
e9d376f0f   Jason Baron   dynamic debug: co...
694
695
696
  
  	if (len == 0)
  		return 0;
7281491c5   Jim Cromie   dynamic_debug: en...
697
698
699
  	if (len > USER_BUF_PAGE - 1) {
  		pr_warn("expected <%d bytes into control
  ", USER_BUF_PAGE);
e9d376f0f   Jason Baron   dynamic debug: co...
700
  		return -E2BIG;
7281491c5   Jim Cromie   dynamic_debug: en...
701
  	}
16e5c1fc3   Al Viro   convert a bunch o...
702
703
704
  	tmpbuf = memdup_user_nul(ubuf, len);
  	if (IS_ERR(tmpbuf))
  		return PTR_ERR(tmpbuf);
b8ccd5dee   Jim Cromie   dynamic_debug: re...
705
706
  	vpr_info("read %d bytes from userspace
  ", (int)len);
e9d376f0f   Jason Baron   dynamic debug: co...
707

8e59b5cfb   Jim Cromie   dynamic_debug: ad...
708
  	ret = ddebug_exec_queries(tmpbuf, NULL);
7281491c5   Jim Cromie   dynamic_debug: en...
709
  	kfree(tmpbuf);
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
710
  	if (ret < 0)
fd89cfb87   Thomas Renninger   Dynamic Debug: Sp...
711
  		return ret;
e9d376f0f   Jason Baron   dynamic debug: co...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
  
  	*offp += len;
  	return len;
  }
  
  /*
   * Set the iterator to point to the first _ddebug object
   * and return a pointer to that first object.  Returns
   * NULL if there are no _ddebugs at all.
   */
  static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
  {
  	if (list_empty(&ddebug_tables)) {
  		iter->table = NULL;
  		iter->idx = 0;
  		return NULL;
  	}
  	iter->table = list_entry(ddebug_tables.next,
  				 struct ddebug_table, link);
  	iter->idx = 0;
  	return &iter->table->ddebugs[iter->idx];
  }
  
  /*
   * Advance the iterator to point to the next _ddebug
   * object from the one the iterator currently points at,
   * and returns a pointer to the new _ddebug.  Returns
   * NULL if the iterator has seen all the _ddebugs.
   */
  static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
  {
  	if (iter->table == NULL)
  		return NULL;
  	if (++iter->idx == iter->table->num_ddebugs) {
  		/* iterate to next table */
  		iter->idx = 0;
  		if (list_is_last(&iter->table->link, &ddebug_tables)) {
  			iter->table = NULL;
  			return NULL;
  		}
  		iter->table = list_entry(iter->table->link.next,
  					 struct ddebug_table, link);
  	}
  	return &iter->table->ddebugs[iter->idx];
  }
  
  /*
   * Seq_ops start method.  Called at the start of every
   * read() call from userspace.  Takes the ddebug_lock and
   * seeks the seq_file's iterator to the given position.
   */
  static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
  {
  	struct ddebug_iter *iter = m->private;
  	struct _ddebug *dp;
  	int n = *pos;
b8ccd5dee   Jim Cromie   dynamic_debug: re...
768
769
  	vpr_info("called m=%p *pos=%lld
  ", m, (unsigned long long)*pos);
e9d376f0f   Jason Baron   dynamic debug: co...
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
  
  	mutex_lock(&ddebug_lock);
  
  	if (!n)
  		return SEQ_START_TOKEN;
  	if (n < 0)
  		return NULL;
  	dp = ddebug_iter_first(iter);
  	while (dp != NULL && --n > 0)
  		dp = ddebug_iter_next(iter);
  	return dp;
  }
  
  /*
   * Seq_ops next method.  Called several times within a read()
   * call from userspace, with ddebug_lock held.  Walks to the
   * next _ddebug object with a special case for the header line.
   */
  static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
  {
  	struct ddebug_iter *iter = m->private;
  	struct _ddebug *dp;
b8ccd5dee   Jim Cromie   dynamic_debug: re...
792
793
  	vpr_info("called m=%p p=%p *pos=%lld
  ",
f657fd21e   Joe Perches   dynamic_debug: Fi...
794
  		 m, p, (unsigned long long)*pos);
e9d376f0f   Jason Baron   dynamic debug: co...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  
  	if (p == SEQ_START_TOKEN)
  		dp = ddebug_iter_first(iter);
  	else
  		dp = ddebug_iter_next(iter);
  	++*pos;
  	return dp;
  }
  
  /*
   * Seq_ops show method.  Called several times within a read()
   * call from userspace, with ddebug_lock held.  Formats the
   * current _ddebug as a single human-readable line, with a
   * special case for the header line.
   */
  static int ddebug_proc_show(struct seq_file *m, void *p)
  {
  	struct ddebug_iter *iter = m->private;
  	struct _ddebug *dp = p;
5ca7d2a6c   Jim Cromie   dynamic_debug: de...
814
  	char flagsbuf[10];
e9d376f0f   Jason Baron   dynamic debug: co...
815

b8ccd5dee   Jim Cromie   dynamic_debug: re...
816
817
  	vpr_info("called m=%p p=%p
  ", m, p);
e9d376f0f   Jason Baron   dynamic debug: co...
818
819
820
  
  	if (p == SEQ_START_TOKEN) {
  		seq_puts(m,
f657fd21e   Joe Perches   dynamic_debug: Fi...
821
822
  			 "# filename:lineno [module]function flags format
  ");
e9d376f0f   Jason Baron   dynamic debug: co...
823
824
  		return 0;
  	}
5ca7d2a6c   Jim Cromie   dynamic_debug: de...
825
  	seq_printf(m, "%s:%u [%s]%s =%s \"",
f657fd21e   Joe Perches   dynamic_debug: Fi...
826
827
828
  		   trim_prefix(dp->filename), dp->lineno,
  		   iter->table->mod_name, dp->function,
  		   ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf)));
e9d376f0f   Jason Baron   dynamic debug: co...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  	seq_escape(m, dp->format, "\t\r
  \"");
  	seq_puts(m, "\"
  ");
  
  	return 0;
  }
  
  /*
   * Seq_ops stop method.  Called at the end of each read()
   * call from userspace.  Drops ddebug_lock.
   */
  static void ddebug_proc_stop(struct seq_file *m, void *p)
  {
b8ccd5dee   Jim Cromie   dynamic_debug: re...
843
844
  	vpr_info("called m=%p p=%p
  ", m, p);
e9d376f0f   Jason Baron   dynamic debug: co...
845
846
847
848
849
850
851
852
853
854
855
  	mutex_unlock(&ddebug_lock);
  }
  
  static const struct seq_operations ddebug_proc_seqops = {
  	.start = ddebug_proc_start,
  	.next = ddebug_proc_next,
  	.show = ddebug_proc_show,
  	.stop = ddebug_proc_stop
  };
  
  /*
07100be7e   Jim Cromie   dynamic_debug: fi...
856
857
858
859
860
   * File_ops->open method for <debugfs>/dynamic_debug/control.  Does
   * the seq_file setup dance, and also creates an iterator to walk the
   * _ddebugs.  Note that we create a seq_file always, even for O_WRONLY
   * files where it's not needed, as doing so simplifies the ->release
   * method.
e9d376f0f   Jason Baron   dynamic debug: co...
861
862
863
   */
  static int ddebug_proc_open(struct inode *inode, struct file *file)
  {
b8ccd5dee   Jim Cromie   dynamic_debug: re...
864
865
  	vpr_info("called
  ");
4bad78c55   Rob Jones   lib/dynamic_debug...
866
867
  	return seq_open_private(file, &ddebug_proc_seqops,
  				sizeof(struct ddebug_iter));
e9d376f0f   Jason Baron   dynamic debug: co...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
  }
  
  static const struct file_operations ddebug_proc_fops = {
  	.owner = THIS_MODULE,
  	.open = ddebug_proc_open,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = seq_release_private,
  	.write = ddebug_proc_write
  };
  
  /*
   * Allocate a new ddebug_table for the given module
   * and add it to the global list.
   */
  int ddebug_add_module(struct _ddebug *tab, unsigned int n,
  			     const char *name)
  {
  	struct ddebug_table *dt;
e9d376f0f   Jason Baron   dynamic debug: co...
887
888
  
  	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
513770f54   Rasmus Villemoes   dynamic_debug: mo...
889
890
891
  	if (dt == NULL) {
  		pr_err("error adding module: %s
  ", name);
e9d376f0f   Jason Baron   dynamic debug: co...
892
  		return -ENOMEM;
513770f54   Rasmus Villemoes   dynamic_debug: mo...
893
  	}
cdf6d0069   Rasmus Villemoes   dynamic_debug: do...
894
895
896
897
898
899
900
  	/*
  	 * For built-in modules, name lives in .rodata and is
  	 * immortal. For loaded modules, name points at the name[]
  	 * member of struct module, which lives at least as long as
  	 * this struct ddebug_table.
  	 */
  	dt->mod_name = name;
e9d376f0f   Jason Baron   dynamic debug: co...
901
  	dt->num_ddebugs = n;
e9d376f0f   Jason Baron   dynamic debug: co...
902
903
904
905
906
  	dt->ddebugs = tab;
  
  	mutex_lock(&ddebug_lock);
  	list_add_tail(&dt->link, &ddebug_tables);
  	mutex_unlock(&ddebug_lock);
b8ccd5dee   Jim Cromie   dynamic_debug: re...
907
908
  	vpr_info("%u debug prints in module %s
  ", n, dt->mod_name);
e9d376f0f   Jason Baron   dynamic debug: co...
909
910
  	return 0;
  }
e9d376f0f   Jason Baron   dynamic debug: co...
911

6ab676e96   Jim Cromie   dynamic_debug: co...
912
913
914
  /* helper for ddebug_dyndbg_(boot|module)_param_cb */
  static int ddebug_dyndbg_param_cb(char *param, char *val,
  				const char *modname, int on_err)
b48420c1d   Jim Cromie   dynamic_debug: ma...
915
  {
b48420c1d   Jim Cromie   dynamic_debug: ma...
916
917
918
919
  	char *sep;
  
  	sep = strchr(param, '.');
  	if (sep) {
6ab676e96   Jim Cromie   dynamic_debug: co...
920
  		/* needed only for ddebug_dyndbg_boot_param_cb */
b48420c1d   Jim Cromie   dynamic_debug: ma...
921
922
923
924
925
  		*sep = '\0';
  		modname = param;
  		param = sep + 1;
  	}
  	if (strcmp(param, "dyndbg"))
6ab676e96   Jim Cromie   dynamic_debug: co...
926
  		return on_err; /* determined by caller */
b48420c1d   Jim Cromie   dynamic_debug: ma...
927

8e59b5cfb   Jim Cromie   dynamic_debug: ad...
928
  	ddebug_exec_queries((val ? val : "+p"), modname);
b48420c1d   Jim Cromie   dynamic_debug: ma...
929
930
  	return 0; /* query failure shouldnt stop module load */
  }
6ab676e96   Jim Cromie   dynamic_debug: co...
931
932
  /* handle both dyndbg and $module.dyndbg params at boot */
  static int ddebug_dyndbg_boot_param_cb(char *param, char *val,
ecc861705   Luis R. Rodriguez   module: add extra...
933
  				const char *unused, void *arg)
b48420c1d   Jim Cromie   dynamic_debug: ma...
934
  {
6ab676e96   Jim Cromie   dynamic_debug: co...
935
936
937
938
  	vpr_info("%s=\"%s\"
  ", param, val);
  	return ddebug_dyndbg_param_cb(param, val, NULL, 0);
  }
b48420c1d   Jim Cromie   dynamic_debug: ma...
939

6ab676e96   Jim Cromie   dynamic_debug: co...
940
941
942
943
944
945
946
947
948
949
  /*
   * modprobe foo finds foo.params in boot-args, strips "foo.", and
   * passes them to load_module().  This callback gets unknown params,
   * processes dyndbg params, rejects others.
   */
  int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *module)
  {
  	vpr_info("module: %s %s=\"%s\"
  ", module, param, val);
  	return ddebug_dyndbg_param_cb(param, val, module, -ENOENT);
b48420c1d   Jim Cromie   dynamic_debug: ma...
950
  }
e9d376f0f   Jason Baron   dynamic debug: co...
951
952
953
  static void ddebug_table_free(struct ddebug_table *dt)
  {
  	list_del_init(&dt->link);
e9d376f0f   Jason Baron   dynamic debug: co...
954
955
956
957
958
959
960
  	kfree(dt);
  }
  
  /*
   * Called in response to a module being unloaded.  Removes
   * any ddebug_table's which point at the module.
   */
ff49d74ad   Yehuda Sadeh   module: initializ...
961
  int ddebug_remove_module(const char *mod_name)
e9d376f0f   Jason Baron   dynamic debug: co...
962
963
964
  {
  	struct ddebug_table *dt, *nextdt;
  	int ret = -ENOENT;
b8ccd5dee   Jim Cromie   dynamic_debug: re...
965
966
  	vpr_info("removing module \"%s\"
  ", mod_name);
e9d376f0f   Jason Baron   dynamic debug: co...
967
968
969
  
  	mutex_lock(&ddebug_lock);
  	list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
4573fe154   Rasmus Villemoes   dynamic_debug: us...
970
  		if (dt->mod_name == mod_name) {
e9d376f0f   Jason Baron   dynamic debug: co...
971
972
  			ddebug_table_free(dt);
  			ret = 0;
4573fe154   Rasmus Villemoes   dynamic_debug: us...
973
  			break;
e9d376f0f   Jason Baron   dynamic debug: co...
974
975
976
977
978
  		}
  	}
  	mutex_unlock(&ddebug_lock);
  	return ret;
  }
e9d376f0f   Jason Baron   dynamic debug: co...
979
980
981
982
983
984
985
986
987
988
989
990
  
  static void ddebug_remove_all_tables(void)
  {
  	mutex_lock(&ddebug_lock);
  	while (!list_empty(&ddebug_tables)) {
  		struct ddebug_table *dt = list_entry(ddebug_tables.next,
  						      struct ddebug_table,
  						      link);
  		ddebug_table_free(dt);
  	}
  	mutex_unlock(&ddebug_lock);
  }
6a5c083de   Thomas Renninger   Dynamic Debug: In...
991
992
993
  static __initdata int ddebug_init_success;
  
  static int __init dynamic_debug_init_debugfs(void)
e9d376f0f   Jason Baron   dynamic debug: co...
994
  {
9fd714cd7   Greg Kroah-Hartman   lib: dynamic_debu...
995
  	struct dentry *dir;
6a5c083de   Thomas Renninger   Dynamic Debug: In...
996
997
998
  
  	if (!ddebug_init_success)
  		return -ENODEV;
e9d376f0f   Jason Baron   dynamic debug: co...
999
1000
  
  	dir = debugfs_create_dir("dynamic_debug", NULL);
9fd714cd7   Greg Kroah-Hartman   lib: dynamic_debu...
1001
  	debugfs_create_file("control", 0644, dir, NULL, &ddebug_proc_fops);
6a5c083de   Thomas Renninger   Dynamic Debug: In...
1002
1003
1004
1005
1006
1007
1008
  	return 0;
  }
  
  static int __init dynamic_debug_init(void)
  {
  	struct _ddebug *iter, *iter_start;
  	const char *modname = NULL;
b48420c1d   Jim Cromie   dynamic_debug: ma...
1009
  	char *cmdline;
6a5c083de   Thomas Renninger   Dynamic Debug: In...
1010
  	int ret = 0;
410769276   Jim Cromie   dynamic_debug: pr...
1011
1012
  	int n = 0, entries = 0, modct = 0;
  	int verbose_bytes = 0;
6a5c083de   Thomas Renninger   Dynamic Debug: In...
1013

b5b78f838   Jim Cromie   dynamic_debug: ea...
1014
  	if (__start___verbose == __stop___verbose) {
f657fd21e   Joe Perches   dynamic_debug: Fi...
1015
1016
  		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build
  ");
b5b78f838   Jim Cromie   dynamic_debug: ea...
1017
1018
1019
1020
1021
1022
  		return 1;
  	}
  	iter = __start___verbose;
  	modname = iter->modname;
  	iter_start = iter;
  	for (; iter < __stop___verbose; iter++) {
410769276   Jim Cromie   dynamic_debug: pr...
1023
1024
1025
  		entries++;
  		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
  			+ strlen(iter->filename) + strlen(iter->format);
b5b78f838   Jim Cromie   dynamic_debug: ea...
1026
  		if (strcmp(modname, iter->modname)) {
410769276   Jim Cromie   dynamic_debug: pr...
1027
  			modct++;
b5b78f838   Jim Cromie   dynamic_debug: ea...
1028
1029
  			ret = ddebug_add_module(iter_start, n, modname);
  			if (ret)
af442399f   Jim Cromie   dynamic_debug: si...
1030
  				goto out_err;
b5b78f838   Jim Cromie   dynamic_debug: ea...
1031
1032
1033
  			n = 0;
  			modname = iter->modname;
  			iter_start = iter;
e9d376f0f   Jason Baron   dynamic debug: co...
1034
  		}
b5b78f838   Jim Cromie   dynamic_debug: ea...
1035
  		n++;
e9d376f0f   Jason Baron   dynamic debug: co...
1036
  	}
b5b78f838   Jim Cromie   dynamic_debug: ea...
1037
1038
  	ret = ddebug_add_module(iter_start, n, modname);
  	if (ret)
af442399f   Jim Cromie   dynamic_debug: si...
1039
  		goto out_err;
a648ec05b   Thomas Renninger   Dynamic Debug: In...
1040

af442399f   Jim Cromie   dynamic_debug: si...
1041
  	ddebug_init_success = 1;
f657fd21e   Joe Perches   dynamic_debug: Fi...
1042
1043
1044
1045
  	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section
  ",
  		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
  		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
af442399f   Jim Cromie   dynamic_debug: si...
1046
1047
  
  	/* apply ddebug_query boot param, dont unload tables on err */
a648ec05b   Thomas Renninger   Dynamic Debug: In...
1048
  	if (ddebug_setup_string[0] != '\0') {
f657fd21e   Joe Perches   dynamic_debug: Fi...
1049
1050
  		pr_warn("ddebug_query param name is deprecated, change it to dyndbg
  ");
8e59b5cfb   Jim Cromie   dynamic_debug: ad...
1051
  		ret = ddebug_exec_queries(ddebug_setup_string, NULL);
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
1052
  		if (ret < 0)
f657fd21e   Joe Perches   dynamic_debug: Fi...
1053
1054
  			pr_warn("Invalid ddebug boot param %s
  ",
4ad275e5c   Joe Perches   dynamic_debug: Co...
1055
  				ddebug_setup_string);
a648ec05b   Thomas Renninger   Dynamic Debug: In...
1056
  		else
85f7f6c0e   Jim Cromie   dynamic_debug: pr...
1057
1058
  			pr_info("%d changes by ddebug_query
  ", ret);
a648ec05b   Thomas Renninger   Dynamic Debug: In...
1059
  	}
b48420c1d   Jim Cromie   dynamic_debug: ma...
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  	/* now that ddebug tables are loaded, process all boot args
  	 * again to find and activate queries given in dyndbg params.
  	 * While this has already been done for known boot params, it
  	 * ignored the unknown ones (dyndbg in particular).  Reusing
  	 * parse_args avoids ad-hoc parsing.  This will also attempt
  	 * to activate queries for not-yet-loaded modules, which is
  	 * slightly noisy if verbose, but harmless.
  	 */
  	cmdline = kstrdup(saved_command_line, GFP_KERNEL);
  	parse_args("dyndbg params", cmdline, NULL,
ecc861705   Luis R. Rodriguez   module: add extra...
1070
  		   0, 0, 0, NULL, &ddebug_dyndbg_boot_param_cb);
b48420c1d   Jim Cromie   dynamic_debug: ma...
1071
  	kfree(cmdline);
af442399f   Jim Cromie   dynamic_debug: si...
1072
  	return 0;
a648ec05b   Thomas Renninger   Dynamic Debug: In...
1073

af442399f   Jim Cromie   dynamic_debug: si...
1074
1075
  out_err:
  	ddebug_remove_all_tables();
e9d376f0f   Jason Baron   dynamic debug: co...
1076
1077
  	return 0;
  }
6a5c083de   Thomas Renninger   Dynamic Debug: In...
1078
  /* Allow early initialization for boot messages via boot param */
3ec5652ab   Jim Cromie   dynamic_debug: in...
1079
  early_initcall(dynamic_debug_init);
b48420c1d   Jim Cromie   dynamic_debug: ma...
1080

6a5c083de   Thomas Renninger   Dynamic Debug: In...
1081
  /* Debugfs setup must be done later */
3ec5652ab   Jim Cromie   dynamic_debug: in...
1082
  fs_initcall(dynamic_debug_init_debugfs);