diff options
| -rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 15 | ||||
| -rw-r--r-- | include/linux/device.h | 2 | ||||
| -rw-r--r-- | include/linux/dynamic_debug.h | 88 | ||||
| -rw-r--r-- | include/linux/dynamic_printk.h | 93 | ||||
| -rw-r--r-- | include/linux/kernel.h | 4 | ||||
| -rw-r--r-- | kernel/module.c | 25 | ||||
| -rw-r--r-- | lib/Kconfig.debug | 2 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/dynamic_debug.c | 756 | ||||
| -rw-r--r-- | lib/dynamic_printk.c | 414 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_pptp.c | 2 | ||||
| -rw-r--r-- | scripts/Makefile.lib | 2 | 
13 files changed, 867 insertions, 543 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 54f21a5c262b..3a1aa8a4affc 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1816,11 +1816,6 @@ and is between 256 and 4096 characters. It is defined in the file  			autoconfiguration.  			Ranges are in pairs (memory base and size). -	dynamic_printk	Enables pr_debug()/dev_dbg() calls if -			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. -			These can also be switched on/off via -			<debugfs>/dynamic_printk/modules -  	print-fatal-signals=  			[KNL] debug: print fatal signals  			print-fatal-signals=1: print segfault info to diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c61fab1dd2f8..aca40b93bd28 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -80,6 +80,11 @@  	VMLINUX_SYMBOL(__start___tracepoints) = .;			\  	*(__tracepoints)						\  	VMLINUX_SYMBOL(__stop___tracepoints) = .;			\ +	/* implement dynamic printk debug */				\ +	. = ALIGN(8);							\ +	VMLINUX_SYMBOL(__start___verbose) = .;                          \ +	*(__verbose)                                                    \ +	VMLINUX_SYMBOL(__stop___verbose) = .;				\  	LIKELY_PROFILE()		       				\  	BRANCH_PROFILE() @@ -309,15 +314,7 @@  	CPU_DISCARD(init.data)						\  	CPU_DISCARD(init.rodata)					\  	MEM_DISCARD(init.data)						\ -	MEM_DISCARD(init.rodata)					\ -	/* implement dynamic printk debug */				\ -	VMLINUX_SYMBOL(__start___verbose_strings) = .;                  \ -	*(__verbose_strings)                                            \ -	VMLINUX_SYMBOL(__stop___verbose_strings) = .;                   \ -	. = ALIGN(8);							\ -	VMLINUX_SYMBOL(__start___verbose) = .;                          \ -	*(__verbose)                                                    \ -	VMLINUX_SYMBOL(__stop___verbose) = .; +	MEM_DISCARD(init.rodata)  #define INIT_TEXT							\  	*(.init.text)							\ diff --git a/include/linux/device.h b/include/linux/device.h index f98d0cfb4f81..2918c0e8fdfd 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -582,7 +582,7 @@ extern const char *dev_driver_string(const struct device *dev);  #if defined(DEBUG)  #define dev_dbg(dev, format, arg...)		\  	dev_printk(KERN_DEBUG , dev , format , ## arg) -#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#elif defined(CONFIG_DYNAMIC_DEBUG)  #define dev_dbg(dev, format, ...) do { \  	dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \  	} while (0) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h new file mode 100644 index 000000000000..07781aaa1164 --- /dev/null +++ b/include/linux/dynamic_debug.h @@ -0,0 +1,88 @@ +#ifndef _DYNAMIC_DEBUG_H +#define _DYNAMIC_DEBUG_H + +/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They + * use independent hash functions, to reduce the chance of false positives. + */ +extern long long dynamic_debug_enabled; +extern long long dynamic_debug_enabled2; + +/* + * An instance of this structure is created in a special + * ELF section at every dynamic debug callsite.  At runtime, + * the special section is treated as an array of these. + */ +struct _ddebug { +	/* +	 * These fields are used to drive the user interface +	 * for selecting and displaying debug callsites. +	 */ +	const char *modname; +	const char *function; +	const char *filename; +	const char *format; +	char primary_hash; +	char secondary_hash; +	unsigned int lineno:24; +	/* + 	 * The flags field controls the behaviour at the callsite. + 	 * The bits here are changed dynamically when the user + 	 * writes commands to <debugfs>/dynamic_debug/ddebug +	 */ +#define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */ +#define _DPRINTK_FLAGS_DEFAULT 0 +	unsigned int flags:8; +} __attribute__((aligned(8))); + + +int ddebug_add_module(struct _ddebug *tab, unsigned int n, +				const char *modname); + +#if defined(CONFIG_DYNAMIC_DEBUG) +extern int ddebug_remove_module(char *mod_name); + +#define __dynamic_dbg_enabled(dd)  ({	     \ +	int __ret = 0;							     \ +	if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) &&	     \ +			(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2))))   \ +				if (unlikely(dd.flags))			     \ +					__ret = 1;			     \ +	__ret; }) + +#define dynamic_pr_debug(fmt, ...) do {					\ +	static struct _ddebug descriptor				\ +	__used								\ +	__attribute__((section("__verbose"), aligned(8))) =		\ +	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\ +		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\ +	if (__dynamic_dbg_enabled(descriptor))				\ +		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		\ +				##__VA_ARGS__);				\ +	} while (0) + + +#define dynamic_dev_dbg(dev, fmt, ...) do {				\ +	static struct _ddebug descriptor				\ +	__used								\ +	__attribute__((section("__verbose"), aligned(8))) =		\ +	{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH,	\ +		DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT };	\ +	if (__dynamic_dbg_enabled(descriptor))				\ +			dev_printk(KERN_DEBUG, dev,			\ +					KBUILD_MODNAME ": " fmt,	\ +					##__VA_ARGS__);			\ +	} while (0) + +#else + +static inline int ddebug_remove_module(char *mod) +{ +	return 0; +} + +#define dynamic_pr_debug(fmt, ...)  do { } while (0) +#define dynamic_dev_dbg(dev, format, ...)  do { } while (0) +#endif + +#endif diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h deleted file mode 100644 index 2d528d009074..000000000000 --- a/include/linux/dynamic_printk.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _DYNAMIC_PRINTK_H -#define _DYNAMIC_PRINTK_H - -#define DYNAMIC_DEBUG_HASH_BITS 6 -#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS) - -#define TYPE_BOOLEAN 1 - -#define DYNAMIC_ENABLED_ALL 0 -#define DYNAMIC_ENABLED_NONE 1 -#define DYNAMIC_ENABLED_SOME 2 - -extern int dynamic_enabled; - -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -extern long long dynamic_printk_enabled; -extern long long dynamic_printk_enabled2; - -struct mod_debug { -	char *modname; -	char *logical_modname; -	char *flag_names; -	int type; -	int hash; -	int hash2; -} __attribute__((aligned(8))); - -int register_dynamic_debug_module(char *mod_name, int type, char *share_name, -					char *flags, int hash, int hash2); - -#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG) -extern int unregister_dynamic_debug_module(char *mod_name); -extern int __dynamic_dbg_enabled_helper(char *modname, int type, -					int value, int hash); - -#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({	     \ -	int __ret = 0;							     \ -	if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) &&	     \ -			(dynamic_printk_enabled2 & (1LL << DEBUG_HASH2))))   \ -			__ret = __dynamic_dbg_enabled_helper(module, type,   \ -								value, hash);\ -	__ret; }) - -#define dynamic_pr_debug(fmt, ...) do {					    \ -	static char mod_name[]						    \ -	__attribute__((section("__verbose_strings")))			    \ -	 = KBUILD_MODNAME;						    \ -	static struct mod_debug descriptor				    \ -	__used								    \ -	__attribute__((section("__verbose"), aligned(8))) =		    \ -	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ -	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \ -						0, 0, DEBUG_HASH))	    \ -		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		    \ -				##__VA_ARGS__);				    \ -	} while (0) - -#define dynamic_dev_dbg(dev, format, ...) do {				    \ -	static char mod_name[]						    \ -	__attribute__((section("__verbose_strings")))			    \ -	 = KBUILD_MODNAME;						    \ -	static struct mod_debug descriptor				    \ -	__used								    \ -	__attribute__((section("__verbose"), aligned(8))) =		    \ -	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ -	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \ -						0, 0, DEBUG_HASH))	    \ -			dev_printk(KERN_DEBUG, dev,			    \ -					KBUILD_MODNAME ": " format,	    \ -					##__VA_ARGS__);			    \ -	} while (0) - -#else - -static inline int unregister_dynamic_debug_module(const char *mod_name) -{ -	return 0; -} -static inline int __dynamic_dbg_enabled_helper(char *modname, int type, -						int value, int hash) -{ -	return 0; -} - -#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({ 0; }) -#define dynamic_pr_debug(fmt, ...)  do { } while (0) -#define dynamic_dev_dbg(dev, format, ...)  do { } while (0) -#endif - -#endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 7fa371898e3e..b5496ecbec71 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -16,7 +16,7 @@  #include <linux/log2.h>  #include <linux/typecheck.h>  #include <linux/ratelimit.h> -#include <linux/dynamic_printk.h> +#include <linux/dynamic_debug.h>  #include <asm/byteorder.h>  #include <asm/bug.h> @@ -358,7 +358,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)  #if defined(DEBUG)  #define pr_debug(fmt, ...) \  	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) -#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#elif defined(CONFIG_DYNAMIC_DEBUG)  #define pr_debug(fmt, ...) do { \  	dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \  	} while (0) diff --git a/kernel/module.c b/kernel/module.c index 1196f5d11700..77672233387f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -822,7 +822,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,  	mutex_lock(&module_mutex);  	/* Store the name of the last unloaded module for diagnostic purposes */  	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); -	unregister_dynamic_debug_module(mod->name); +	ddebug_remove_module(mod->name);  	free_module(mod);   out: @@ -1827,19 +1827,13 @@ static inline void add_kallsyms(struct module *mod,  }  #endif /* CONFIG_KALLSYMS */ -static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num) +static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)  { -#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG -	unsigned int i; - -	for (i = 0; i < num; i++) { -		register_dynamic_debug_module(debug[i].modname, -					      debug[i].type, -					      debug[i].logical_modname, -					      debug[i].flag_names, -					      debug[i].hash, debug[i].hash2); -	} -#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ +#ifdef CONFIG_DYNAMIC_DEBUG +	if (ddebug_add_module(debug, num, debug->modname)) +		printk(KERN_ERR "dynamic debug error adding module: %s\n", +					debug->modname); +#endif  }  static void *module_alloc_update_bounds(unsigned long size) @@ -2213,12 +2207,13 @@ static noinline struct module *load_module(void __user *umod,  	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);  	if (!mod->taints) { -		struct mod_debug *debug; +		struct _ddebug *debug;  		unsigned int num_debug;  		debug = section_objs(hdr, sechdrs, secstrings, "__verbose",  				     sizeof(*debug), &num_debug); -		dynamic_printk_setup(debug, num_debug); +		if (debug) +			dynamic_debug_setup(debug, num_debug);  	}  	/* sechdrs[0].sh_size is always zero */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1bcf9cd4baa0..0dd1c04c7323 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -847,7 +847,7 @@ config BUILD_DOCSRC  	  Say N if you are unsure. -config DYNAMIC_PRINTK_DEBUG +config DYNAMIC_DEBUG  	bool "Enable dynamic printk() call support"  	default n  	depends on PRINTK diff --git a/lib/Makefile b/lib/Makefile index 32b0e64ded27..8633d6be9d21 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -82,7 +82,7 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o  obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o -obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o +obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o  hostprogs-y	:= gen_crc32table  clean-files	:= crc32table.h diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c new file mode 100644 index 000000000000..9e123ae326bc --- /dev/null +++ b/lib/dynamic_debug.c @@ -0,0 +1,756 @@ +/* + * 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kallsyms.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/mutex.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/list.h> +#include <linux/sysctl.h> +#include <linux/ctype.h> +#include <linux/uaccess.h> +#include <linux/dynamic_debug.h> +#include <linux/debugfs.h> + +extern struct _ddebug __start___verbose[]; +extern struct _ddebug __stop___verbose[]; + +/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They + * use independent hash functions, to reduce the chance of false positives. + */ +long long dynamic_debug_enabled; +EXPORT_SYMBOL_GPL(dynamic_debug_enabled); +long long dynamic_debug_enabled2; +EXPORT_SYMBOL_GPL(dynamic_debug_enabled2); + +struct ddebug_table { +	struct list_head link; +	char *mod_name; +	unsigned int num_ddebugs; +	unsigned int num_enabled; +	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); +static int verbose = 0; + +/* Return the last part of a pathname */ +static inline const char *basename(const char *path) +{ +	const char *tail = strrchr(path, '/'); +	return tail ? tail+1 : path; +} + +/* 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; + +	BUG_ON(maxlen < 4); +	if (dp->flags & _DPRINTK_FLAGS_PRINT) +		*p++ = 'p'; +	if (p == buf) +		*p++ = '-'; +	*p = '\0'; + +	return buf; +} + +/* + * must be called with ddebug_lock held + */ + +static int disabled_hash(char hash, bool first_table) +{ +	struct ddebug_table *dt; +	char table_hash_value; + +	list_for_each_entry(dt, &ddebug_tables, link) { +		if (first_table) +			table_hash_value = dt->ddebugs->primary_hash; +		else +			table_hash_value = dt->ddebugs->secondary_hash; +		if (dt->num_enabled && (hash == table_hash_value)) +			return 0; +	} +	return 1; +} + +/* + * Search the tables for _ddebug's which match the given + * `query' and apply the `flags' and `mask' to them.  Tells + * the user which ddebug's were changed, or whether none + * were matched. + */ +static void ddebug_change(const struct ddebug_query *query, +			   unsigned int flags, unsigned int mask) +{ +	int i; +	struct ddebug_table *dt; +	unsigned int newflags; +	unsigned int nfound = 0; +	char flagbuf[8]; + +	/* search for matching ddebugs */ +	mutex_lock(&ddebug_lock); +	list_for_each_entry(dt, &ddebug_tables, link) { + +		/* match against the module name */ +		if (query->module != NULL && +		    strcmp(query->module, dt->mod_name)) +			continue; + +		for (i = 0 ; i < dt->num_ddebugs ; i++) { +			struct _ddebug *dp = &dt->ddebugs[i]; + +			/* match against the source filename */ +			if (query->filename != NULL && +			    strcmp(query->filename, dp->filename) && +			    strcmp(query->filename, basename(dp->filename))) +				continue; + +			/* match against the function */ +			if (query->function != NULL && +			    strcmp(query->function, dp->function)) +				continue; + +			/* match against the format */ +			if (query->format != NULL && +			    strstr(dp->format, query->format) == NULL) +				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; + +			if (!newflags) +				dt->num_enabled--; +			else if (!dp-flags) +				dt->num_enabled++; +			dp->flags = newflags; +			if (newflags) { +				dynamic_debug_enabled |= +						(1LL << dp->primary_hash); +				dynamic_debug_enabled2 |= +						(1LL << dp->secondary_hash); +			} else { +				if (disabled_hash(dp->primary_hash, true)) +					dynamic_debug_enabled &= +						~(1LL << dp->primary_hash); +				if (disabled_hash(dp->secondary_hash, false)) +					dynamic_debug_enabled2 &= +						~(1LL << dp->secondary_hash); +			} +			if (verbose) +				printk(KERN_INFO +					"ddebug: changed %s:%d [%s]%s %s\n", +					dp->filename, dp->lineno, +					dt->mod_name, dp->function, +					ddebug_describe_flags(dp, flagbuf, +							sizeof(flagbuf))); +		} +	} +	mutex_unlock(&ddebug_lock); + +	if (!nfound && verbose) +		printk(KERN_INFO "ddebug: no matches for query\n"); +} + +/* + * Wrapper around strsep() to collapse the multiple empty tokens + * that it returns when fed sequences of separator characters. + * Now, if we had strtok_r()... + */ +static inline char *nearly_strtok_r(char **p, const char *sep) +{ +	char *r; + +	while ((r = strsep(p, sep)) != NULL && *r == '\0') +		; +	return r; +} + +/* + * Split the buffer `buf' into space-separated words. + * Return the number of such words or <0 on error. + */ +static int ddebug_tokenize(char *buf, char *words[], int maxwords) +{ +	int nwords = 0; + +	while (nwords < maxwords && +	       (words[nwords] = nearly_strtok_r(&buf, " \t\r\n")) != NULL) +		nwords++; +	if (buf) +		return -EINVAL;	/* ran out of words[] before bytes */ + +	if (verbose) { +		int i; +		printk(KERN_INFO "%s: split into words:", __func__); +		for (i = 0 ; i < nwords ; i++) +			printk(" \"%s\"", words[i]); +		printk("\n"); +	} + +	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) +{ +	char *end = NULL; +	BUG_ON(str == NULL); +	if (*str == '\0') { +		*val = 0; +		return 0; +	} +	*val = simple_strtoul(str, &end, 10); +	return end == NULL || end == str || *end != '\0' ? -EINVAL : 0; +} + +/* + * Undo octal escaping in a string, inplace.  This is useful to + * allow the user to express a query which matches a format + * containing embedded spaces. + */ +#define isodigit(c)		((c) >= '0' && (c) <= '7') +static char *unescape(char *str) +{ +	char *in = str; +	char *out = str; + +	while (*in) { +		if (*in == '\\') { +			if (in[1] == '\\') { +				*out++ = '\\'; +				in += 2; +				continue; +			} else if (in[1] == 't') { +				*out++ = '\t'; +				in += 2; +				continue; +			} else if (in[1] == 'n') { +				*out++ = '\n'; +				in += 2; +				continue; +			} else if (isodigit(in[1]) && +			         isodigit(in[2]) && +			         isodigit(in[3])) { +				*out++ = ((in[1] - '0')<<6) | +				          ((in[2] - '0')<<3) | +				          (in[3] - '0'); +				in += 4; +				continue; +			} +		} +		*out++ = *in++; +	} +	*out = '\0'; + +	return str; +} + +/* + * 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 + */ +static int ddebug_parse_query(char *words[], int nwords, +			       struct ddebug_query *query) +{ +	unsigned int i; + +	/* check we have an even number of words */ +	if (nwords % 2 != 0) +		return -EINVAL; +	memset(query, 0, sizeof(*query)); + +	for (i = 0 ; i < nwords ; i += 2) { +		if (!strcmp(words[i], "func")) +			query->function = words[i+1]; +		else if (!strcmp(words[i], "file")) +			query->filename = words[i+1]; +		else if (!strcmp(words[i], "module")) +			query->module = words[i+1]; +		else if (!strcmp(words[i], "format")) +			query->format = unescape(words[i+1]); +		else if (!strcmp(words[i], "line")) { +			char *first = words[i+1]; +			char *last = strchr(first, '-'); +			if (last) +				*last++ = '\0'; +			if (parse_lineno(first, &query->first_lineno) < 0) +				return -EINVAL; +			if (last != NULL) { +				/* range <first>-<last> */ +				if (parse_lineno(last, &query->last_lineno) < 0) +					return -EINVAL; +			} else { +				query->last_lineno = query->first_lineno; +			} +		} else { +			if (verbose) +				printk(KERN_ERR "%s: unknown keyword \"%s\"\n", +					__func__, words[i]); +			return -EINVAL; +		} +	} + +	if (verbose) +		printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" " +		       "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", +			__func__, query->function, query->filename, +			query->module, query->format, query->first_lineno, +			query->last_lineno); + +	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; +	int op = '='; + +	switch (*str) { +	case '+': +	case '-': +	case '=': +		op = *str++; +		break; +	default: +		return -EINVAL; +	} +	if (verbose) +		printk(KERN_INFO "%s: op='%c'\n", __func__, op); + +	for ( ; *str ; ++str) { +		switch (*str) { +		case 'p': +			flags |= _DPRINTK_FLAGS_PRINT; +			break; +		default: +			return -EINVAL; +		} +	} +	if (flags == 0) +		return -EINVAL; +	if (verbose) +		printk(KERN_INFO "%s: flags=0x%x\n", __func__, flags); + +	/* 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; +	} +	if (verbose) +		printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n", +			__func__, *flagsp, *maskp); +	return 0; +} + +/* + * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the + * command text from userspace, parses and executes it. + */ +static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, +				  size_t len, loff_t *offp) +{ +	unsigned int flags = 0, mask = 0; +	struct ddebug_query query; +#define MAXWORDS 9 +	int nwords; +	char *words[MAXWORDS]; +	char tmpbuf[256]; + +	if (len == 0) +		return 0; +	/* we don't check *offp -- multiple writes() are allowed */ +	if (len > sizeof(tmpbuf)-1) +		return -E2BIG; +	if (copy_from_user(tmpbuf, ubuf, len)) +		return -EFAULT; +	tmpbuf[len] = '\0'; +	if (verbose) +		printk(KERN_INFO "%s: read %d bytes from userspace\n", +			__func__, (int)len); + +	nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); +	if (nwords < 0) +		return -EINVAL; +	if (ddebug_parse_query(words, nwords-1, &query)) +		return -EINVAL; +	if (ddebug_parse_flags(words[nwords-1], &flags, &mask)) +		return -EINVAL; + +	/* actually go and implement the change */ +	ddebug_change(&query, flags, mask); + +	*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; + +	if (verbose) +		printk(KERN_INFO "%s: called m=%p *pos=%lld\n", +			__func__, m, (unsigned long long)*pos); + +	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; + +	if (verbose) +		printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n", +			__func__, m, p, (unsigned long long)*pos); + +	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; +	char flagsbuf[8]; + +	if (verbose) +		printk(KERN_INFO "%s: called m=%p p=%p\n", +			__func__, m, p); + +	if (p == SEQ_START_TOKEN) { +		seq_puts(m, +			"# filename:lineno [module]function flags format\n"); +		return 0; +	} + +	seq_printf(m, "%s:%u [%s]%s %s \"", +		   dp->filename, dp->lineno, +		   iter->table->mod_name, dp->function, +		   ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); +	seq_escape(m, dp->format, "\t\r\n\""); +	seq_puts(m, "\"\n"); + +	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) +{ +	if (verbose) +		printk(KERN_INFO "%s: called m=%p p=%p\n", +			__func__, m, p); +	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 +}; + +/* + * 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. + */ +static int ddebug_proc_open(struct inode *inode, struct file *file) +{ +	struct ddebug_iter *iter; +	int err; + +	if (verbose) +		printk(KERN_INFO "%s: called\n", __func__); + +	iter = kzalloc(sizeof(*iter), GFP_KERNEL); +	if (iter == NULL) +		return -ENOMEM; + +	err = seq_open(file, &ddebug_proc_seqops); +	if (err) { +		kfree(iter); +		return err; +	} +	((struct seq_file *) file->private_data)->private = iter; +	return 0; +} + +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; +	char *new_name; + +	dt = kzalloc(sizeof(*dt), GFP_KERNEL); +	if (dt == NULL) +		return -ENOMEM; +	new_name = kstrdup(name, GFP_KERNEL); +	if (new_name == NULL) { +		kfree(dt); +		return -ENOMEM; +	} +	dt->mod_name = new_name; +	dt->num_ddebugs = n; +	dt->num_enabled = 0; +	dt->ddebugs = tab; + +	mutex_lock(&ddebug_lock); +	list_add_tail(&dt->link, &ddebug_tables); +	mutex_unlock(&ddebug_lock); + +	if (verbose) +		printk(KERN_INFO "%u debug prints in module %s\n", +				 n, dt->mod_name); +	return 0; +} +EXPORT_SYMBOL_GPL(ddebug_add_module); + +static void ddebug_table_free(struct ddebug_table *dt) +{ +	list_del_init(&dt->link); +	kfree(dt->mod_name); +	kfree(dt); +} + +/* + * Called in response to a module being unloaded.  Removes + * any ddebug_table's which point at the module. + */ +int ddebug_remove_module(char *mod_name) +{ +	struct ddebug_table *dt, *nextdt; +	int ret = -ENOENT; + +	if (verbose) +		printk(KERN_INFO "%s: removing module \"%s\"\n", +				__func__, mod_name); + +	mutex_lock(&ddebug_lock); +	list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { +		if (!strcmp(dt->mod_name, mod_name)) { +			ddebug_table_free(dt); +			ret = 0; +		} +	} +	mutex_unlock(&ddebug_lock); +	return ret; +} +EXPORT_SYMBOL_GPL(ddebug_remove_module); + +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); +} + +static int __init dynamic_debug_init(void) +{ +	struct dentry *dir, *file; +	struct _ddebug *iter, *iter_start; +	const char *modname = NULL; +	int ret = 0; +	int n = 0; + +	dir = debugfs_create_dir("dynamic_debug", NULL); +	if (!dir) +		return -ENOMEM; +	file = debugfs_create_file("control", 0644, dir, NULL, +					&ddebug_proc_fops); +	if (!file) { +		debugfs_remove(dir); +		return -ENOMEM; +	} +	if (__start___verbose != __stop___verbose) { +		iter = __start___verbose; +		modname = iter->modname; +		iter_start = iter; +		for (; iter < __stop___verbose; iter++) { +			if (strcmp(modname, iter->modname)) { +				ret = ddebug_add_module(iter_start, n, modname); +				if (ret) +					goto out_free; +				n = 0; +				modname = iter->modname; +				iter_start = iter; +			} +			n++; +		} +		ret = ddebug_add_module(iter_start, n, modname); +	} +out_free: +	if (ret) { +		ddebug_remove_all_tables(); +		debugfs_remove(dir); +		debugfs_remove(file); +	} +	return 0; +} +module_init(dynamic_debug_init); diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c deleted file mode 100644 index 165a19763dc9..000000000000 --- a/lib/dynamic_printk.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * lib/dynamic_printk.c - * - * make pr_debug()/dev_dbg() calls runtime configurable based upon their - * their source module. - * - * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/uaccess.h> -#include <linux/seq_file.h> -#include <linux/debugfs.h> -#include <linux/fs.h> - -extern struct mod_debug __start___verbose[]; -extern struct mod_debug __stop___verbose[]; - -struct debug_name { -	struct hlist_node hlist; -	struct hlist_node hlist2; -	int hash1; -	int hash2; -	char *name; -	int enable; -	int type; -}; - -static int nr_entries; -static int num_enabled; -int dynamic_enabled = DYNAMIC_ENABLED_NONE; -static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] = -	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; -static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] = -	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; -static DECLARE_MUTEX(debug_list_mutex); - -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -long long dynamic_printk_enabled; -EXPORT_SYMBOL_GPL(dynamic_printk_enabled); -long long dynamic_printk_enabled2; -EXPORT_SYMBOL_GPL(dynamic_printk_enabled2); - -/* returns the debug module pointer. */ -static struct debug_name *find_debug_module(char *module_name) -{ -	int i; -	struct hlist_head *head; -	struct hlist_node *node; -	struct debug_name *element; - -	element = NULL; -	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { -		head = &module_table[i]; -		hlist_for_each_entry_rcu(element, node, head, hlist) -			if (!strcmp(element->name, module_name)) -				return element; -	} -	return NULL; -} - -/* returns the debug module pointer. */ -static struct debug_name *find_debug_module_hash(char *module_name, int hash) -{ -	struct hlist_head *head; -	struct hlist_node *node; -	struct debug_name *element; - -	element = NULL; -	head = &module_table[hash]; -	hlist_for_each_entry_rcu(element, node, head, hlist) -		if (!strcmp(element->name, module_name)) -			return element; -	return NULL; -} - -/* caller must hold mutex*/ -static int __add_debug_module(char *mod_name, int hash, int hash2) -{ -	struct debug_name *new; -	char *module_name; -	int ret = 0; - -	if (find_debug_module(mod_name)) { -		ret = -EINVAL; -		goto out; -	} -	module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL); -	if (!module_name) { -		ret = -ENOMEM; -		goto out; -	} -	module_name = strcpy(module_name, mod_name); -	module_name[strlen(mod_name)] = '\0'; -	new = kzalloc(sizeof(struct debug_name), GFP_KERNEL); -	if (!new) { -		kfree(module_name); -		ret = -ENOMEM; -		goto out; -	} -	INIT_HLIST_NODE(&new->hlist); -	INIT_HLIST_NODE(&new->hlist2); -	new->name = module_name; -	new->hash1 = hash; -	new->hash2 = hash2; -	hlist_add_head_rcu(&new->hlist, &module_table[hash]); -	hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]); -	nr_entries++; -out: -	return ret; -} - -int unregister_dynamic_debug_module(char *mod_name) -{ -	struct debug_name *element; -	int ret = 0; - -	down(&debug_list_mutex); -	element = find_debug_module(mod_name); -	if (!element) { -		ret = -EINVAL; -		goto out; -	} -	hlist_del_rcu(&element->hlist); -	hlist_del_rcu(&element->hlist2); -	synchronize_rcu(); -	kfree(element->name); -	if (element->enable) -		num_enabled--; -	kfree(element); -	nr_entries--; -out: -	up(&debug_list_mutex); -	return ret; -} -EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module); - -int register_dynamic_debug_module(char *mod_name, int type, char *share_name, -					char *flags, int hash, int hash2) -{ -	struct debug_name *elem; -	int ret = 0; - -	down(&debug_list_mutex); -	elem = find_debug_module(mod_name); -	if (!elem) { -		if (__add_debug_module(mod_name, hash, hash2)) -			goto out; -		elem = find_debug_module(mod_name); -		if (dynamic_enabled == DYNAMIC_ENABLED_ALL && -				!strcmp(mod_name, share_name)) { -			elem->enable = true; -			num_enabled++; -		} -	} -	elem->type |= type; -out: -	up(&debug_list_mutex); -	return ret; -} -EXPORT_SYMBOL_GPL(register_dynamic_debug_module); - -int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash) -{ -	struct debug_name *elem; -	int ret = 0; - -	if (dynamic_enabled == DYNAMIC_ENABLED_ALL) -		return 1; -	rcu_read_lock(); -	elem = find_debug_module_hash(mod_name, hash); -	if (elem && elem->enable) -		ret = 1; -	rcu_read_unlock(); -	return ret; -} -EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper); - -static void set_all(bool enable) -{ -	struct debug_name *e; -	struct hlist_node *node; -	int i; -	long long enable_mask; - -	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { -		if (module_table[i].first != NULL) { -			hlist_for_each_entry(e, node, &module_table[i], hlist) { -				e->enable = enable; -			} -		} -	} -	if (enable) -		enable_mask = ULLONG_MAX; -	else -		enable_mask = 0; -	dynamic_printk_enabled = enable_mask; -	dynamic_printk_enabled2 = enable_mask; -} - -static int disabled_hash(int i, bool first_table) -{ -	struct debug_name *e; -	struct hlist_node *node; - -	if (first_table) { -		hlist_for_each_entry(e, node, &module_table[i], hlist) { -			if (e->enable) -				return 0; -		} -	} else { -		hlist_for_each_entry(e, node, &module_table2[i], hlist2) { -			if (e->enable) -				return 0; -		} -	} -	return 1; -} - -static ssize_t pr_debug_write(struct file *file, const char __user *buf, -				size_t length, loff_t *ppos) -{ -	char *buffer, *s, *value_str, *setting_str; -	int err, value; -	struct debug_name *elem = NULL; -	int all = 0; - -	if (length > PAGE_SIZE || length < 0) -		return -EINVAL; - -	buffer = (char *)__get_free_page(GFP_KERNEL); -	if (!buffer) -		return -ENOMEM; - -	err = -EFAULT; -	if (copy_from_user(buffer, buf, length)) -		goto out; - -	err = -EINVAL; -	if (length < PAGE_SIZE) -		buffer[length] = '\0'; -	else if (buffer[PAGE_SIZE-1]) -		goto out; - -	err = -EINVAL; -	down(&debug_list_mutex); - -	if (strncmp("set", buffer, 3)) -		goto out_up; -	s = buffer + 3; -	setting_str = strsep(&s, "="); -	if (s == NULL) -		goto out_up; -	setting_str = strstrip(setting_str); -	value_str = strsep(&s, " "); -	if (s == NULL) -		goto out_up; -	s = strstrip(s); -	if (!strncmp(s, "all", 3)) -		all = 1; -	else -		elem = find_debug_module(s); -	if (!strncmp(setting_str, "enable", 6)) { -		value = !!simple_strtol(value_str, NULL, 10); -		if (all) { -			if (value) { -				set_all(true); -				num_enabled = nr_entries; -				dynamic_enabled = DYNAMIC_ENABLED_ALL; -			} else { -				set_all(false); -				num_enabled = 0; -				dynamic_enabled = DYNAMIC_ENABLED_NONE; -			} -			err = 0; -		} else if (elem) { -			if (value && (elem->enable == 0)) { -				dynamic_printk_enabled |= (1LL << elem->hash1); -				dynamic_printk_enabled2 |= (1LL << elem->hash2); -				elem->enable = 1; -				num_enabled++; -				dynamic_enabled = DYNAMIC_ENABLED_SOME; -				err = 0; -				printk(KERN_DEBUG -					"debugging enabled for module %s\n", -					elem->name); -			} else if (!value && (elem->enable == 1)) { -				elem->enable = 0; -				num_enabled--; -				if (disabled_hash(elem->hash1, true)) -					dynamic_printk_enabled &= -							~(1LL << elem->hash1); -				if (disabled_hash(elem->hash2, false)) -					dynamic_printk_enabled2 &= -							~(1LL << elem->hash2); -				if (num_enabled) -					dynamic_enabled = DYNAMIC_ENABLED_SOME; -				else -					dynamic_enabled = DYNAMIC_ENABLED_NONE; -				err = 0; -				printk(KERN_DEBUG -					"debugging disabled for module %s\n", -					elem->name); -			} -		} -	} -	if (!err) -		err = length; -out_up: -	up(&debug_list_mutex); -out: -	free_page((unsigned long)buffer); -	return err; -} - -static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos) -{ -	return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL; -} - -static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ -	(*pos)++; -	if (*pos >= DEBUG_HASH_TABLE_SIZE) -		return NULL; -	return pos; -} - -static void pr_debug_seq_stop(struct seq_file *s, void *v) -{ -	/* Nothing to do */ -} - -static int pr_debug_seq_show(struct seq_file *s, void *v) -{ -	struct hlist_head *head; -	struct hlist_node *node; -	struct debug_name *elem; -	unsigned int i = *(loff_t *) v; - -	rcu_read_lock(); -	head = &module_table[i]; -	hlist_for_each_entry_rcu(elem, node, head, hlist) { -		seq_printf(s, "%s enabled=%d", elem->name, elem->enable); -		seq_printf(s, "\n"); -	} -	rcu_read_unlock(); -	return 0; -} - -static struct seq_operations pr_debug_seq_ops = { -	.start = pr_debug_seq_start, -	.next  = pr_debug_seq_next, -	.stop  = pr_debug_seq_stop, -	.show  = pr_debug_seq_show -}; - -static int pr_debug_open(struct inode *inode, struct file *filp) -{ -	return seq_open(filp, &pr_debug_seq_ops); -} - -static const struct file_operations pr_debug_operations = { -	.open		= pr_debug_open, -	.read		= seq_read, -	.write		= pr_debug_write, -	.llseek		= seq_lseek, -	.release	= seq_release, -}; - -static int __init dynamic_printk_init(void) -{ -	struct dentry *dir, *file; -	struct mod_debug *iter; -	unsigned long value; - -	dir = debugfs_create_dir("dynamic_printk", NULL); -	if (!dir) -		return -ENOMEM; -	file = debugfs_create_file("modules", 0644, dir, NULL, -					&pr_debug_operations); -	if (!file) { -		debugfs_remove(dir); -		return -ENOMEM; -	} -	for (value = (unsigned long)__start___verbose; -		value < (unsigned long)__stop___verbose; -		value += sizeof(struct mod_debug)) { -			iter = (struct mod_debug *)value; -			register_dynamic_debug_module(iter->modname, -				iter->type, -				iter->logical_modname, -				iter->flag_names, iter->hash, iter->hash2); -	} -	if (dynamic_enabled == DYNAMIC_ENABLED_ALL) -		set_all(true); -	return 0; -} -module_init(dynamic_printk_init); -/* may want to move this earlier so we can get traces as early as possible */ - -static int __init dynamic_printk_setup(char *str) -{ -	if (str) -		return -ENOENT; -	dynamic_enabled = DYNAMIC_ENABLED_ALL; -	return 0; -} -/* Use early_param(), so we can get debug output as early as possible */ -early_param("dynamic_printk", dynamic_printk_setup); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 9e169ef2e854..12bd09dbd36c 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -66,7 +66,7 @@ void  			     struct nf_conntrack_expect *exp) __read_mostly;  EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG) +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)  /* PptpControlMessageType names */  const char *const pptp_msg_name[] = {  	"UNKNOWN_MESSAGE", diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index e06365775bdf..c18fa150b6fe 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -97,7 +97,7 @@ modname_flags  = $(if $(filter 1,$(words $(modname))),\                   -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")  #hash values -ifdef CONFIG_DYNAMIC_PRINTK_DEBUG +ifdef CONFIG_DYNAMIC_DEBUG  debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\                -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"  else  | 
