Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9d376f0 authored by Jason Baron's avatar Jason Baron Committed by Greg Kroah-Hartman
Browse files

dynamic debug: combine dprintk and dynamic printk



This patch combines Greg Bank's dprintk() work with the existing dynamic
printk patchset, we are now calling it 'dynamic debug'.

The new feature of this patchset is a richer /debugfs control file interface,
(an example output from my system is at the bottom), which allows fined grained
control over the the debug output. The output can be controlled by function,
file, module, format string, and line number.

for example, enabled all debug messages in module 'nf_conntrack':

echo -n 'module nf_conntrack +p' > /mnt/debugfs/dynamic_debug/control

to disable them:

echo -n 'module nf_conntrack -p' > /mnt/debugfs/dynamic_debug/control

A further explanation can be found in the documentation patch.

Signed-off-by: default avatarGreg Banks <gnb@sgi.com>
Signed-off-by: default avatarJason Baron <jbaron@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 095160ae
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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
+6 −9
Original line number Diff line number Diff line
@@ -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)							\
+1 −1
Original line number Diff line number Diff line
@@ -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)
+88 −0
Original line number Diff line number Diff line
#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

include/linux/dynamic_printk.h

deleted100644 → 0
+0 −93
Original line number Diff line number Diff line
#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
Loading