Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver core: basic infrastructure for per-module dynamic debug messages

Base infrastructure to enable per-module debug messages.

I've introduced CONFIG_DYNAMIC_PRINTK_DEBUG, which when enabled centralizes
control of debugging statements on a per-module basis in one /proc file,
currently, <debugfs>/dynamic_printk/modules. When, CONFIG_DYNAMIC_PRINTK_DEBUG,
is not set, debugging statements can still be enabled as before, often by
defining 'DEBUG' for the proper compilation unit. Thus, this patch set has no
affect when CONFIG_DYNAMIC_PRINTK_DEBUG is not set.

The infrastructure currently ties into all pr_debug() and dev_dbg() calls. That
is, if CONFIG_DYNAMIC_PRINTK_DEBUG is set, all pr_debug() and dev_dbg() calls
can be dynamically enabled/disabled on a per-module basis.

Future plans include extending this functionality to subsystems, that define
their own debug levels and flags.

Usage:

Dynamic debugging is controlled by the debugfs file,
<debugfs>/dynamic_printk/modules. This file contains a list of the modules that
can be enabled. The format of the file is as follows:

<module_name> <enabled=0/1>
.
.
.

<module_name> : Name of the module in which the debug call resides
<enabled=0/1> : whether the messages are enabled or not

For example:

snd_hda_intel enabled=0
fixup enabled=1
driver enabled=0

Enable a module:

$echo "set enabled=1 <module_name>" > dynamic_printk/modules

Disable a module:

$echo "set enabled=0 <module_name>" > dynamic_printk/modules

Enable all modules:

$echo "set enabled=1 all" > dynamic_printk/modules

Disable all modules:

$echo "set enabled=0 all" > dynamic_printk/modules

Finally, passing "dynamic_printk" at the command line enables
debugging for all modules. This mode can be turned off via the above
disable command.

[gkh: minor cleanups and tweaks to make the build work quietly]

Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


authored by

Jason Baron and committed by
Greg Kroah-Hartman
346e15be 33376c1c

+700 -7
+5
Documentation/kernel-parameters.txt
··· 1713 1713 autoconfiguration. 1714 1714 Ranges are in pairs (memory base and size). 1715 1715 1716 + dynamic_printk 1717 + Enables pr_debug()/dev_dbg() calls if 1718 + CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also 1719 + be switched on/off via <debugfs>/dynamic_printk/modules 1720 + 1716 1721 print-fatal-signals= 1717 1722 [KNL] debug: print fatal signals 1718 1723 print-fatal-signals=1: print segfault info to
+9 -1
include/asm-generic/vmlinux.lds.h
··· 268 268 CPU_DISCARD(init.data) \ 269 269 CPU_DISCARD(init.rodata) \ 270 270 MEM_DISCARD(init.data) \ 271 - MEM_DISCARD(init.rodata) 271 + MEM_DISCARD(init.rodata) \ 272 + /* implement dynamic printk debug */ \ 273 + VMLINUX_SYMBOL(__start___verbose_strings) = .; \ 274 + *(__verbose_strings) \ 275 + VMLINUX_SYMBOL(__stop___verbose_strings) = .; \ 276 + . = ALIGN(8); \ 277 + VMLINUX_SYMBOL(__start___verbose) = .; \ 278 + *(__verbose) \ 279 + VMLINUX_SYMBOL(__stop___verbose) = .; 272 280 273 281 #define INIT_TEXT \ 274 282 *(.init.text) \
+5 -1
include/linux/device.h
··· 550 550 #define dev_info(dev, format, arg...) \ 551 551 dev_printk(KERN_INFO , dev , format , ## arg) 552 552 553 - #ifdef DEBUG 553 + #if defined(CONFIG_DYNAMIC_PRINTK_DEBUG) 554 + #define dev_dbg(dev, format, ...) do { \ 555 + dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ 556 + } while (0) 557 + #elif defined(DEBUG) 554 558 #define dev_dbg(dev, format, arg...) \ 555 559 dev_printk(KERN_DEBUG , dev , format , ## arg) 556 560 #else
+93
include/linux/dynamic_printk.h
··· 1 + #ifndef _DYNAMIC_PRINTK_H 2 + #define _DYNAMIC_PRINTK_H 3 + 4 + #define DYNAMIC_DEBUG_HASH_BITS 6 5 + #define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS) 6 + 7 + #define TYPE_BOOLEAN 1 8 + 9 + #define DYNAMIC_ENABLED_ALL 0 10 + #define DYNAMIC_ENABLED_NONE 1 11 + #define DYNAMIC_ENABLED_SOME 2 12 + 13 + extern int dynamic_enabled; 14 + 15 + /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which 16 + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They 17 + * use independent hash functions, to reduce the chance of false positives. 18 + */ 19 + extern long long dynamic_printk_enabled; 20 + extern long long dynamic_printk_enabled2; 21 + 22 + struct mod_debug { 23 + char *modname; 24 + char *logical_modname; 25 + char *flag_names; 26 + int type; 27 + int hash; 28 + int hash2; 29 + } __attribute__((aligned(8))); 30 + 31 + int register_dynamic_debug_module(char *mod_name, int type, char *share_name, 32 + char *flags, int hash, int hash2); 33 + 34 + #if defined(CONFIG_DYNAMIC_PRINTK_DEBUG) 35 + extern int unregister_dynamic_debug_module(char *mod_name); 36 + extern int __dynamic_dbg_enabled_helper(char *modname, int type, 37 + int value, int hash); 38 + 39 + #define __dynamic_dbg_enabled(module, type, value, level, hash) ({ \ 40 + int __ret = 0; \ 41 + if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) && \ 42 + (dynamic_printk_enabled2 & (1LL << DEBUG_HASH2)))) \ 43 + __ret = __dynamic_dbg_enabled_helper(module, type, \ 44 + value, hash);\ 45 + __ret; }) 46 + 47 + #define dynamic_pr_debug(fmt, ...) do { \ 48 + static char mod_name[] \ 49 + __attribute__((section("__verbose_strings"))) \ 50 + = KBUILD_MODNAME; \ 51 + static struct mod_debug descriptor \ 52 + __used \ 53 + __attribute__((section("__verbose"), aligned(8))) = \ 54 + { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ 55 + if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \ 56 + 0, 0, DEBUG_HASH)) \ 57 + printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \ 58 + ##__VA_ARGS__); \ 59 + } while (0) 60 + 61 + #define dynamic_dev_dbg(dev, format, ...) do { \ 62 + static char mod_name[] \ 63 + __attribute__((section("__verbose_strings"))) \ 64 + = KBUILD_MODNAME; \ 65 + static struct mod_debug descriptor \ 66 + __used \ 67 + __attribute__((section("__verbose"), aligned(8))) = \ 68 + { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\ 69 + if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \ 70 + 0, 0, DEBUG_HASH)) \ 71 + dev_printk(KERN_DEBUG, dev, \ 72 + KBUILD_MODNAME ": " format, \ 73 + ##__VA_ARGS__); \ 74 + } while (0) 75 + 76 + #else 77 + 78 + static inline int unregister_dynamic_debug_module(const char *mod_name) 79 + { 80 + return 0; 81 + } 82 + static inline int __dynamic_dbg_enabled_helper(char *modname, int type, 83 + int value, int hash) 84 + { 85 + return 0; 86 + } 87 + 88 + #define __dynamic_dbg_enabled(module, type, value, level, hash) ({ 0; }) 89 + #define dynamic_pr_debug(fmt, ...) do { } while (0) 90 + #define dynamic_dev_dbg(dev, format, ...) do { } while (0) 91 + #endif 92 + 93 + #endif
+6 -1
include/linux/kernel.h
··· 16 16 #include <linux/log2.h> 17 17 #include <linux/typecheck.h> 18 18 #include <linux/ratelimit.h> 19 + #include <linux/dynamic_printk.h> 19 20 #include <asm/byteorder.h> 20 21 #include <asm/bug.h> 21 22 ··· 304 303 #define pr_info(fmt, arg...) \ 305 304 printk(KERN_INFO fmt, ##arg) 306 305 307 - #ifdef DEBUG 308 306 /* If you are writing a driver, please use dev_dbg instead */ 307 + #if defined(CONFIG_DYNAMIC_PRINTK_DEBUG) 308 + #define pr_debug(fmt, ...) do { \ 309 + dynamic_pr_debug(fmt, ##__VA_ARGS__); \ 310 + } while (0) 311 + #elif defined(DEBUG) 309 312 #define pr_debug(fmt, arg...) \ 310 313 printk(KERN_DEBUG fmt, ##arg) 311 314 #else
-1
include/linux/module.h
··· 345 345 /* Reference counts */ 346 346 struct module_ref ref[NR_CPUS]; 347 347 #endif 348 - 349 348 }; 350 349 #ifndef MODULE_ARCH_INIT 351 350 #define MODULE_ARCH_INIT {}
+31
kernel/module.c
··· 784 784 mutex_lock(&module_mutex); 785 785 /* Store the name of the last unloaded module for diagnostic purposes */ 786 786 strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); 787 + unregister_dynamic_debug_module(mod->name); 787 788 free_module(mod); 788 789 789 790 out: ··· 1784 1783 } 1785 1784 #endif /* CONFIG_KALLSYMS */ 1786 1785 1786 + #ifdef CONFIG_DYNAMIC_PRINTK_DEBUG 1787 + static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex) 1788 + { 1789 + struct mod_debug *debug_info; 1790 + unsigned long pos, end; 1791 + unsigned int num_verbose; 1792 + 1793 + pos = sechdrs[verboseindex].sh_addr; 1794 + num_verbose = sechdrs[verboseindex].sh_size / 1795 + sizeof(struct mod_debug); 1796 + end = pos + (num_verbose * sizeof(struct mod_debug)); 1797 + 1798 + for (; pos < end; pos += sizeof(struct mod_debug)) { 1799 + debug_info = (struct mod_debug *)pos; 1800 + register_dynamic_debug_module(debug_info->modname, 1801 + debug_info->type, debug_info->logical_modname, 1802 + debug_info->flag_names, debug_info->hash, 1803 + debug_info->hash2); 1804 + } 1805 + } 1806 + #else 1807 + static inline void dynamic_printk_setup(Elf_Shdr *sechdrs, 1808 + unsigned int verboseindex) 1809 + { 1810 + } 1811 + #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ 1812 + 1787 1813 static void *module_alloc_update_bounds(unsigned long size) 1788 1814 { 1789 1815 void *ret = module_alloc(size); ··· 1859 1831 #endif 1860 1832 unsigned int markersindex; 1861 1833 unsigned int markersstringsindex; 1834 + unsigned int verboseindex; 1862 1835 struct module *mod; 1863 1836 long err = 0; 1864 1837 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ ··· 2146 2117 markersindex = find_sec(hdr, sechdrs, secstrings, "__markers"); 2147 2118 markersstringsindex = find_sec(hdr, sechdrs, secstrings, 2148 2119 "__markers_strings"); 2120 + verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose"); 2149 2121 2150 2122 /* Now do relocations. */ 2151 2123 for (i = 1; i < hdr->e_shnum; i++) { ··· 2197 2167 marker_update_probe_range(mod->markers, 2198 2168 mod->markers + mod->num_markers); 2199 2169 #endif 2170 + dynamic_printk_setup(sechdrs, verboseindex); 2200 2171 err = module_finalize(hdr, sechdrs, mod); 2201 2172 if (err < 0) 2202 2173 goto cleanup;
+55
lib/Kconfig.debug
··· 807 807 808 808 Say N if you are unsure. 809 809 810 + config DYNAMIC_PRINTK_DEBUG 811 + bool "Enable dynamic printk() call support" 812 + default n 813 + depends on PRINTK 814 + select PRINTK_DEBUG 815 + help 816 + 817 + Compiles debug level messages into the kernel, which would not 818 + otherwise be available at runtime. These messages can then be 819 + enabled/disabled on a per module basis. This mechanism implicitly 820 + enables all pr_debug() and dev_dbg() calls. The impact of this 821 + compile option is a larger kernel text size of about 2%. 822 + 823 + Usage: 824 + 825 + Dynamic debugging is controlled by the debugfs file, 826 + dynamic_printk/modules. This file contains a list of the modules that 827 + can be enabled. The format of the file is the module name, followed 828 + by a set of flags that can be enabled. The first flag is always the 829 + 'enabled' flag. For example: 830 + 831 + <module_name> <enabled=0/1> 832 + . 833 + . 834 + . 835 + 836 + <module_name> : Name of the module in which the debug call resides 837 + <enabled=0/1> : whether the messages are enabled or not 838 + 839 + From a live system: 840 + 841 + snd_hda_intel enabled=0 842 + fixup enabled=0 843 + driver enabled=0 844 + 845 + Enable a module: 846 + 847 + $echo "set enabled=1 <module_name>" > dynamic_printk/modules 848 + 849 + Disable a module: 850 + 851 + $echo "set enabled=0 <module_name>" > dynamic_printk/modules 852 + 853 + Enable all modules: 854 + 855 + $echo "set enabled=1 all" > dynamic_printk/modules 856 + 857 + Disable all modules: 858 + 859 + $echo "set enabled=0 all" > dynamic_printk/modules 860 + 861 + Finally, passing "dynamic_printk" at the command line enables 862 + debugging for all modules. This mode can be turned off via the above 863 + disable command. 864 + 810 865 source "samples/Kconfig" 811 866 812 867 source "lib/Kconfig.kgdb"
+2
lib/Makefile
··· 81 81 82 82 obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o 83 83 84 + obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o 85 + 84 86 hostprogs-y := gen_crc32table 85 87 clean-files := crc32table.h 86 88
+418
lib/dynamic_printk.c
··· 1 + /* 2 + * lib/dynamic_printk.c 3 + * 4 + * make pr_debug()/dev_dbg() calls runtime configurable based upon their 5 + * their source module. 6 + * 7 + * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com> 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/uaccess.h> 13 + #include <linux/seq_file.h> 14 + #include <linux/debugfs.h> 15 + #include <linux/fs.h> 16 + 17 + extern struct mod_debug __start___verbose[]; 18 + extern struct mod_debug __stop___verbose[]; 19 + 20 + struct debug_name { 21 + struct hlist_node hlist; 22 + struct hlist_node hlist2; 23 + int hash1; 24 + int hash2; 25 + char *name; 26 + int enable; 27 + int type; 28 + }; 29 + 30 + static int nr_entries; 31 + static int num_enabled; 32 + int dynamic_enabled = DYNAMIC_ENABLED_NONE; 33 + static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] = 34 + { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; 35 + static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] = 36 + { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT }; 37 + static DECLARE_MUTEX(debug_list_mutex); 38 + 39 + /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which 40 + * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They 41 + * use independent hash functions, to reduce the chance of false positives. 42 + */ 43 + long long dynamic_printk_enabled; 44 + EXPORT_SYMBOL_GPL(dynamic_printk_enabled); 45 + long long dynamic_printk_enabled2; 46 + EXPORT_SYMBOL_GPL(dynamic_printk_enabled2); 47 + 48 + /* returns the debug module pointer. */ 49 + static struct debug_name *find_debug_module(char *module_name) 50 + { 51 + int i; 52 + struct hlist_head *head; 53 + struct hlist_node *node; 54 + struct debug_name *element; 55 + 56 + element = NULL; 57 + for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { 58 + head = &module_table[i]; 59 + hlist_for_each_entry_rcu(element, node, head, hlist) 60 + if (!strcmp(element->name, module_name)) 61 + return element; 62 + } 63 + return NULL; 64 + } 65 + 66 + /* returns the debug module pointer. */ 67 + static struct debug_name *find_debug_module_hash(char *module_name, int hash) 68 + { 69 + struct hlist_head *head; 70 + struct hlist_node *node; 71 + struct debug_name *element; 72 + 73 + element = NULL; 74 + head = &module_table[hash]; 75 + hlist_for_each_entry_rcu(element, node, head, hlist) 76 + if (!strcmp(element->name, module_name)) 77 + return element; 78 + return NULL; 79 + } 80 + 81 + /* caller must hold mutex*/ 82 + static int __add_debug_module(char *mod_name, int hash, int hash2) 83 + { 84 + struct debug_name *new; 85 + char *module_name; 86 + int ret = 0; 87 + 88 + if (find_debug_module(mod_name)) { 89 + ret = -EINVAL; 90 + goto out; 91 + } 92 + module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL); 93 + if (!module_name) { 94 + ret = -ENOMEM; 95 + goto out; 96 + } 97 + module_name = strcpy(module_name, mod_name); 98 + module_name[strlen(mod_name)] = '\0'; 99 + new = kzalloc(sizeof(struct debug_name), GFP_KERNEL); 100 + if (!new) { 101 + kfree(module_name); 102 + ret = -ENOMEM; 103 + goto out; 104 + } 105 + INIT_HLIST_NODE(&new->hlist); 106 + INIT_HLIST_NODE(&new->hlist2); 107 + new->name = module_name; 108 + new->hash1 = hash; 109 + new->hash2 = hash2; 110 + hlist_add_head_rcu(&new->hlist, &module_table[hash]); 111 + hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]); 112 + nr_entries++; 113 + out: 114 + return ret; 115 + } 116 + 117 + int unregister_dynamic_debug_module(char *mod_name) 118 + { 119 + struct debug_name *element; 120 + int ret = 0; 121 + 122 + down(&debug_list_mutex); 123 + element = find_debug_module(mod_name); 124 + if (!element) { 125 + ret = -EINVAL; 126 + goto out; 127 + } 128 + hlist_del_rcu(&element->hlist); 129 + hlist_del_rcu(&element->hlist2); 130 + synchronize_rcu(); 131 + kfree(element->name); 132 + if (element->enable) 133 + num_enabled--; 134 + kfree(element); 135 + nr_entries--; 136 + out: 137 + up(&debug_list_mutex); 138 + return 0; 139 + } 140 + EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module); 141 + 142 + int register_dynamic_debug_module(char *mod_name, int type, char *share_name, 143 + char *flags, int hash, int hash2) 144 + { 145 + struct debug_name *elem; 146 + int ret = 0; 147 + 148 + down(&debug_list_mutex); 149 + elem = find_debug_module(mod_name); 150 + if (!elem) { 151 + if (__add_debug_module(mod_name, hash, hash2)) 152 + goto out; 153 + elem = find_debug_module(mod_name); 154 + if (dynamic_enabled == DYNAMIC_ENABLED_ALL && 155 + !strcmp(mod_name, share_name)) { 156 + elem->enable = true; 157 + num_enabled++; 158 + } 159 + } 160 + elem->type |= type; 161 + out: 162 + up(&debug_list_mutex); 163 + return ret; 164 + } 165 + EXPORT_SYMBOL_GPL(register_dynamic_debug_module); 166 + 167 + int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash) 168 + { 169 + struct debug_name *elem; 170 + int ret = 0; 171 + 172 + if (dynamic_enabled == DYNAMIC_ENABLED_ALL) 173 + return 1; 174 + rcu_read_lock(); 175 + elem = find_debug_module_hash(mod_name, hash); 176 + if (elem && elem->enable) 177 + ret = 1; 178 + rcu_read_unlock(); 179 + return ret; 180 + } 181 + EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper); 182 + 183 + static void set_all(bool enable) 184 + { 185 + struct debug_name *e; 186 + struct hlist_node *node; 187 + int i; 188 + long long enable_mask; 189 + 190 + for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) { 191 + if (module_table[i].first != NULL) { 192 + hlist_for_each_entry(e, node, &module_table[i], hlist) { 193 + e->enable = enable; 194 + } 195 + } 196 + } 197 + if (enable) 198 + enable_mask = ULLONG_MAX; 199 + else 200 + enable_mask = 0; 201 + dynamic_printk_enabled = enable_mask; 202 + dynamic_printk_enabled2 = enable_mask; 203 + } 204 + 205 + static int disabled_hash(int i, bool first_table) 206 + { 207 + struct debug_name *e; 208 + struct hlist_node *node; 209 + 210 + if (first_table) { 211 + hlist_for_each_entry(e, node, &module_table[i], hlist) { 212 + if (e->enable) 213 + return 0; 214 + } 215 + } else { 216 + hlist_for_each_entry(e, node, &module_table2[i], hlist2) { 217 + if (e->enable) 218 + return 0; 219 + } 220 + } 221 + return 1; 222 + } 223 + 224 + static ssize_t pr_debug_write(struct file *file, const char __user *buf, 225 + size_t length, loff_t *ppos) 226 + { 227 + char *buffer, *s, *value_str, *setting_str; 228 + int err, value; 229 + struct debug_name *elem = NULL; 230 + int all = 0; 231 + 232 + if (length > PAGE_SIZE || length < 0) 233 + return -EINVAL; 234 + 235 + buffer = (char *)__get_free_page(GFP_KERNEL); 236 + if (!buffer) 237 + return -ENOMEM; 238 + 239 + err = -EFAULT; 240 + if (copy_from_user(buffer, buf, length)) 241 + goto out; 242 + 243 + err = -EINVAL; 244 + if (length < PAGE_SIZE) 245 + buffer[length] = '\0'; 246 + else if (buffer[PAGE_SIZE-1]) 247 + goto out; 248 + 249 + err = -EINVAL; 250 + down(&debug_list_mutex); 251 + 252 + if (strncmp("set", buffer, 3)) 253 + goto out_up; 254 + s = buffer + 3; 255 + setting_str = strsep(&s, "="); 256 + if (s == NULL) 257 + goto out_up; 258 + setting_str = strstrip(setting_str); 259 + value_str = strsep(&s, " "); 260 + if (s == NULL) 261 + goto out_up; 262 + s = strstrip(s); 263 + if (!strncmp(s, "all", 3)) 264 + all = 1; 265 + else 266 + elem = find_debug_module(s); 267 + if (!strncmp(setting_str, "enable", 6)) { 268 + value = !!simple_strtol(value_str, NULL, 10); 269 + if (all) { 270 + if (value) { 271 + set_all(true); 272 + num_enabled = nr_entries; 273 + dynamic_enabled = DYNAMIC_ENABLED_ALL; 274 + } else { 275 + set_all(false); 276 + num_enabled = 0; 277 + dynamic_enabled = DYNAMIC_ENABLED_NONE; 278 + } 279 + err = 0; 280 + } else { 281 + if (elem) { 282 + if (value && (elem->enable == 0)) { 283 + dynamic_printk_enabled |= 284 + (1LL << elem->hash1); 285 + dynamic_printk_enabled2 |= 286 + (1LL << elem->hash2); 287 + elem->enable = 1; 288 + num_enabled++; 289 + dynamic_enabled = DYNAMIC_ENABLED_SOME; 290 + err = 0; 291 + printk(KERN_DEBUG 292 + "debugging enabled for module %s", 293 + elem->name); 294 + } else if (!value && (elem->enable == 1)) { 295 + elem->enable = 0; 296 + num_enabled--; 297 + if (disabled_hash(elem->hash1, true)) 298 + dynamic_printk_enabled &= 299 + ~(1LL << elem->hash1); 300 + if (disabled_hash(elem->hash2, false)) 301 + dynamic_printk_enabled2 &= 302 + ~(1LL << elem->hash2); 303 + if (num_enabled) 304 + dynamic_enabled = 305 + DYNAMIC_ENABLED_SOME; 306 + else 307 + dynamic_enabled = 308 + DYNAMIC_ENABLED_NONE; 309 + err = 0; 310 + printk(KERN_DEBUG 311 + "debugging disabled for module " 312 + "%s", elem->name); 313 + } 314 + } 315 + } 316 + } 317 + if (!err) 318 + err = length; 319 + out_up: 320 + up(&debug_list_mutex); 321 + out: 322 + free_page((unsigned long)buffer); 323 + return err; 324 + } 325 + 326 + static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos) 327 + { 328 + return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL; 329 + } 330 + 331 + static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos) 332 + { 333 + (*pos)++; 334 + if (*pos >= DEBUG_HASH_TABLE_SIZE) 335 + return NULL; 336 + return pos; 337 + } 338 + 339 + static void pr_debug_seq_stop(struct seq_file *s, void *v) 340 + { 341 + /* Nothing to do */ 342 + } 343 + 344 + static int pr_debug_seq_show(struct seq_file *s, void *v) 345 + { 346 + struct hlist_head *head; 347 + struct hlist_node *node; 348 + struct debug_name *elem; 349 + unsigned int i = *(loff_t *) v; 350 + 351 + rcu_read_lock(); 352 + head = &module_table[i]; 353 + hlist_for_each_entry_rcu(elem, node, head, hlist) { 354 + seq_printf(s, "%s enabled=%d", elem->name, elem->enable); 355 + seq_printf(s, "\n"); 356 + } 357 + rcu_read_unlock(); 358 + return 0; 359 + } 360 + 361 + static struct seq_operations pr_debug_seq_ops = { 362 + .start = pr_debug_seq_start, 363 + .next = pr_debug_seq_next, 364 + .stop = pr_debug_seq_stop, 365 + .show = pr_debug_seq_show 366 + }; 367 + 368 + static int pr_debug_open(struct inode *inode, struct file *filp) 369 + { 370 + return seq_open(filp, &pr_debug_seq_ops); 371 + } 372 + 373 + static const struct file_operations pr_debug_operations = { 374 + .open = pr_debug_open, 375 + .read = seq_read, 376 + .write = pr_debug_write, 377 + .llseek = seq_lseek, 378 + .release = seq_release, 379 + }; 380 + 381 + static int __init dynamic_printk_init(void) 382 + { 383 + struct dentry *dir, *file; 384 + struct mod_debug *iter; 385 + unsigned long value; 386 + 387 + dir = debugfs_create_dir("dynamic_printk", NULL); 388 + if (!dir) 389 + return -ENOMEM; 390 + file = debugfs_create_file("modules", 0644, dir, NULL, 391 + &pr_debug_operations); 392 + if (!file) { 393 + debugfs_remove(dir); 394 + return -ENOMEM; 395 + } 396 + for (value = (unsigned long)__start___verbose; 397 + value < (unsigned long)__stop___verbose; 398 + value += sizeof(struct mod_debug)) { 399 + iter = (struct mod_debug *)value; 400 + register_dynamic_debug_module(iter->modname, 401 + iter->type, 402 + iter->logical_modname, 403 + iter->flag_names, iter->hash, iter->hash2); 404 + } 405 + return 0; 406 + } 407 + module_init(dynamic_printk_init); 408 + /* may want to move this earlier so we can get traces as early as possible */ 409 + 410 + static int __init dynamic_printk_setup(char *str) 411 + { 412 + if (str) 413 + return -ENOENT; 414 + set_all(true); 415 + return 0; 416 + } 417 + /* Use early_param(), so we can get debug output as early as possible */ 418 + early_param("dynamic_printk", dynamic_printk_setup);
+1 -1
net/netfilter/nf_conntrack_pptp.c
··· 65 65 struct nf_conntrack_expect *exp) __read_mostly; 66 66 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn); 67 67 68 - #ifdef DEBUG 68 + #if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG) 69 69 /* PptpControlMessageType names */ 70 70 const char *const pptp_msg_name[] = { 71 71 "UNKNOWN_MESSAGE",
+10 -1
scripts/Makefile.lib
··· 96 96 modname_flags = $(if $(filter 1,$(words $(modname))),\ 97 97 -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") 98 98 99 + #hash values 100 + ifdef CONFIG_DYNAMIC_PRINTK_DEBUG 101 + debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\ 102 + -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))" 103 + else 104 + debug_flags = 105 + endif 106 + 99 107 orig_c_flags = $(KBUILD_CFLAGS) $(ccflags-y) $(CFLAGS_$(basetarget).o) 100 108 _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) 101 109 _a_flags = $(KBUILD_AFLAGS) $(asflags-y) $(AFLAGS_$(basetarget).o) ··· 129 121 130 122 c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \ 131 123 $(__c_flags) $(modkern_cflags) \ 132 - -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) 124 + -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \ 125 + $(debug_flags) 133 126 134 127 a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \ 135 128 $(__a_flags) $(modkern_aflags)
+1 -1
scripts/basic/Makefile
··· 9 9 # fixdep: Used to generate dependency information during build process 10 10 # docproc: Used in Documentation/DocBook 11 11 12 - hostprogs-y := fixdep docproc 12 + hostprogs-y := fixdep docproc hash 13 13 always := $(hostprogs-y) 14 14 15 15 # fixdep is needed to compile other host programs
+64
scripts/basic/hash.c
··· 1 + /* 2 + * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com> 3 + * 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + #include <string.h> 9 + 10 + #define DYNAMIC_DEBUG_HASH_BITS 6 11 + 12 + static const char *program; 13 + 14 + static void usage(void) 15 + { 16 + printf("Usage: %s <djb2|r5> <modname>\n", program); 17 + exit(1); 18 + } 19 + 20 + /* djb2 hashing algorithm by Dan Bernstein. From: 21 + * http://www.cse.yorku.ca/~oz/hash.html 22 + */ 23 + 24 + unsigned int djb2_hash(char *str) 25 + { 26 + unsigned long hash = 5381; 27 + int c; 28 + 29 + c = *str; 30 + while (c) { 31 + hash = ((hash << 5) + hash) + c; 32 + c = *++str; 33 + } 34 + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); 35 + } 36 + 37 + unsigned int r5_hash(char *str) 38 + { 39 + unsigned long hash = 0; 40 + int c; 41 + 42 + c = *str; 43 + while (c) { 44 + hash = (hash + (c << 4) + (c >> 4)) * 11; 45 + c = *++str; 46 + } 47 + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); 48 + } 49 + 50 + int main(int argc, char *argv[]) 51 + { 52 + program = argv[0]; 53 + 54 + if (argc != 3) 55 + usage(); 56 + if (!strcmp(argv[1], "djb2")) 57 + printf("%d\n", djb2_hash(argv[2])); 58 + else if (!strcmp(argv[1], "r5")) 59 + printf("%d\n", r5_hash(argv[2])); 60 + else 61 + usage(); 62 + exit(0); 63 + } 64 +