diff options
author | Kent Overstreet <kmo@daterainc.com> | 2014-11-04 15:20:14 -0800 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2015-01-26 14:42:10 -0800 |
commit | 17ffcfa8c2ca2f5fc01c04673e967ba0fcd8b690 (patch) | |
tree | 3cc5dde8b16d5b9658d8d700d9a857472851c586 | |
parent | ad82c9a399c14be27972a6f44608e523383eb18f (diff) |
dynamic faults: classes, frequencies, new parsing
Change-Id: Id0d6e748e220d7550b4da61356d5a33a5036ab0f
-rw-r--r-- | include/linux/dynamic_fault.h | 93 | ||||
-rw-r--r-- | lib/dynamic_fault.c | 476 |
2 files changed, 302 insertions, 267 deletions
diff --git a/include/linux/dynamic_fault.h b/include/linux/dynamic_fault.h index 850ebe1053ee..ce1626d70fab 100644 --- a/include/linux/dynamic_fault.h +++ b/include/linux/dynamic_fault.h @@ -5,6 +5,23 @@ #include <linux/jump_label.h> #include <linux/slab.h> +enum dfault_enabled { + DFAULT_DISABLED, + DFAULT_ENABLED, + DFAULT_ONESHOT, +}; + +union dfault_state { + struct { + unsigned enabled:2; + unsigned count:30; + }; + + struct { + unsigned v; + }; +}; + /* * An instance of this structure is created in a special * ELF section at every dynamic fault callsite. At runtime, @@ -14,39 +31,25 @@ struct _dfault { const char *modname; const char *function; const char *filename; - unsigned int lineno:16; - unsigned int index:16; - /* - * 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 _DFAULT_ON (1<<0) -#define _DFAULT_ONE_SHOT (1<<1) - unsigned int flags:8; + const char *class; + + const u16 lineno; + u16 index; + + unsigned frequency; + union dfault_state state; + struct static_key enabled; } __attribute__((aligned(8))); #ifdef CONFIG_DYNAMIC_FAULT -extern long long dynamic_fault_enabled; -extern long long dynamic_fault_enabled2; - int dfault_add_module(struct _dfault *tab, unsigned int n, const char *mod); int dfault_remove_module(char *mod_name); +bool __dynamic_fault_enabled(struct _dfault *); -#define __dynamic_fault_enabled(df) \ -({ \ - int __ret = 0; \ - if (static_key_true(&(df).enabled)) { \ - __ret = df.flags; \ - df.flags &= ~_DFAULT_ONE_SHOT; \ - } \ - __ret; \ -}) - -#define dynamic_fault() \ +#define dynamic_fault(_class) \ ({ \ static struct _dfault descriptor \ __used __attribute__((section("__faults"), aligned(8))) = { \ @@ -54,48 +57,62 @@ int dfault_remove_module(char *mod_name); .function = __func__, \ .filename = __FILE__, \ .lineno = __LINE__, \ + .class = _class, \ }; \ - __dynamic_fault_enabled(descriptor); \ + \ + static_key_false(&descriptor.enabled) && \ + __dynamic_fault_enabled(&descriptor); \ }) +#define memory_fault() dynamic_fault("memory") +#define race_fault() dynamic_fault("race") + #define kmalloc(...) \ - (dynamic_fault() ? NULL : kmalloc(__VA_ARGS__)) + (memory_fault() ? NULL : kmalloc(__VA_ARGS__)) #define kzalloc(...) \ - (dynamic_fault() ? NULL : kzalloc(__VA_ARGS__)) + (memory_fault() ? NULL : kzalloc(__VA_ARGS__)) #define krealloc(...) \ - (dynamic_fault() ? NULL : krealloc(__VA_ARGS__)) + (memory_fault() ? NULL : krealloc(__VA_ARGS__)) #define __get_free_pages(...) \ - (dynamic_fault() ? 0 : __get_free_pages(__VA_ARGS__)) + (memory_fault() ? 0 : __get_free_pages(__VA_ARGS__)) #define alloc_pages_node(...) \ - (dynamic_fault() ? NULL : alloc_pages_node(__VA_ARGS__)) + (memory_fault() ? NULL : alloc_pages_node(__VA_ARGS__)) #define alloc_pages_nodemask(...) \ - (dynamic_fault() ? NULL : alloc_pages_nodemask(__VA_ARGS__)) + (memory_fault() ? NULL : alloc_pages_nodemask(__VA_ARGS__)) #define bio_alloc_bioset(gfp, ...) \ - (!(gfp & __GFP_WAIT) && dynamic_fault() \ + (!(gfp & __GFP_WAIT) && memory_fault() \ ? NULL : bio_alloc_bioset(gfp, __VA_ARGS__)) #define bio_clone(bio, gfp) \ - (!(gfp & __GFP_WAIT) && dynamic_fault() \ + (!(gfp & __GFP_WAIT) && memory_fault() \ ? NULL : bio_clone(bio, gfp)) #define bio_clone_bioset(bio, gfp, bs) \ - (!(gfp & __GFP_WAIT) && dynamic_fault() \ + (!(gfp & __GFP_WAIT) && memory_fault() \ ? NULL : bio_clone_bioset(bio, gfp, bs)) #define bio_kmalloc(...) \ - (dynamic_fault() ? NULL : bio_kmalloc(__VA_ARGS__)) + (memory_fault() ? NULL : bio_kmalloc(__VA_ARGS__)) #define bio_clone_kmalloc(...) \ - (dynamic_fault() ? NULL : bio_clone_kmalloc(__VA_ARGS__)) + (memory_fault() ? NULL : bio_clone_kmalloc(__VA_ARGS__)) #define bio_alloc_pages(...) \ - (dynamic_fault() ? -ENOMEM : bio_alloc_pages(__VA_ARGS__)) + (memory_fault() ? -ENOMEM : bio_alloc_pages(__VA_ARGS__)) + +#define bio_get_user_pages(bio, uaddr, len, write_to_vm) \ + bio_get_user_pages(bio, uaddr, \ + memory_fault() ? min_t(unsigned long, len, PAGE_SIZE) \ + : len, \ + write_to_vm) #else /* CONFIG_DYNAMIC_FAULT */ #define dfault_add_module(tab, n, modname) 0 #define dfault_remove_module(mod) 0 -#define dynamic_fault() 0 +#define dynamic_fault(_class) 0 +#define memory_fault() 0 +#define race_fault() 0 #endif /* CONFIG_DYNAMIC_FAULT */ diff --git a/lib/dynamic_fault.c b/lib/dynamic_fault.c index d55cec90bf8f..7e0a1a105e8a 100644 --- a/lib/dynamic_fault.c +++ b/lib/dynamic_fault.c @@ -12,6 +12,8 @@ * */ +#define pr_fmt(fmt) "%s(): " fmt "\n", __func__ + #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -30,32 +32,31 @@ #include <linux/debugfs.h> #include <linux/slab.h> +#undef kzalloc + extern struct _dfault __start___faults[]; extern struct _dfault __stop___faults[]; -/* dynamic_fault_enabled, and dynamic_fault_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_fault_enabled; -EXPORT_SYMBOL_GPL(dynamic_fault_enabled); -long long dynamic_fault_enabled2; -EXPORT_SYMBOL_GPL(dynamic_fault_enabled2); - struct dfault_table { struct list_head link; char *mod_name; unsigned int num_dfaults; - unsigned int num_enabled; struct _dfault *dfaults; }; struct dfault_query { - const char *filename; - const char *module; - const char *function; - unsigned int first_lineno, last_lineno; - unsigned int first_index, last_index; + const char *filename; + const char *module; + const char *function; + const char *class; + unsigned int first_lineno, last_lineno; + unsigned int first_index, last_index; + + unsigned set_enabled:1; + unsigned enabled:2; + + unsigned set_frequency:1; + unsigned frequency; }; struct dfault_iter { @@ -65,7 +66,33 @@ struct dfault_iter { static DEFINE_MUTEX(dfault_lock); static LIST_HEAD(dfault_tables); -static int verbose; + +bool __dynamic_fault_enabled(struct _dfault *df) +{ + union dfault_state old, new; + unsigned v = df->state.v; + bool ret; + + do { + old.v = new.v = v; + + if (new.enabled == DFAULT_DISABLED) + return false; + + ret = df->frequency + ? ++new.count >= df->frequency + : true; + if (ret) + new.count = 0; + if (ret && new.enabled == DFAULT_ONESHOT) + new.enabled = DFAULT_DISABLED; + } while ((v = cmpxchg(&df->state.v, old.v, new.v)) != old.v); + + if (ret) + pr_debug("returned true for %s:%u", df->filename, df->lineno); + + return ret; +} /* Return the last part of a pathname */ static inline const char *basename(const char *path) @@ -75,19 +102,21 @@ static inline const char *basename(const char *path) } /* format a string into buf[] which describes the _dfault's flags */ -static char *dfault_describe_flags(struct _dfault *df, char *buf, - size_t maxlen) +static char *dfault_describe_flags(struct _dfault *df, char *buf, size_t buflen) { - char *p = buf; - - BUG_ON(maxlen < 4); - if (df->flags & _DFAULT_ON) - *p++ = 'f'; - if (df->flags & _DFAULT_ONE_SHOT) - *p++ = 'o'; - if (p == buf) - *p++ = '-'; - *p = '\0'; + switch (df->state.enabled) { + case DFAULT_DISABLED: + strlcpy(buf, "disabled", buflen); + break; + case DFAULT_ENABLED: + strlcpy(buf, "enabled", buflen); + break; + case DFAULT_ONESHOT: + strlcpy(buf, "oneshot", buflen); + break; + default: + BUG(); + } return buf; } @@ -102,14 +131,12 @@ static char *dfault_describe_flags(struct _dfault *df, char *buf, * the user which dfault's were changed, or whether none * were matched. */ -static int dfault_change(const struct dfault_query *query, - unsigned int flags, unsigned int mask) +static int dfault_change(const struct dfault_query *query) { int i; struct dfault_table *dt; - unsigned int newflags; unsigned int nfound = 0; - char flagbuf[8]; + char flagbuf[16]; /* search for matching dfaults */ mutex_lock(&dfault_lock); @@ -134,6 +161,17 @@ static int dfault_change(const struct dfault_query *query, strcmp(query->function, df->function)) continue; + /* match against the class */ + if (query->class) { + size_t len = strlen(query->class); + + if (strncmp(query->class, df->class, len)) + continue; + + if (df->class[len] && df->class[len] != ':') + continue; + } + /* match against the line number range */ if (query->first_lineno && df->lineno < query->first_lineno) @@ -152,36 +190,31 @@ static int dfault_change(const struct dfault_query *query, nfound++; - newflags = (df->flags & mask) | flags; - if (newflags == df->flags) - continue; + if (query->set_enabled && + query->enabled != df->state.enabled) { + if (query->enabled != DFAULT_DISABLED) + static_key_slow_inc(&df->enabled); + else if (df->state.enabled != DFAULT_DISABLED) + static_key_slow_dec(&df->enabled); + + df->state.enabled = query->enabled; + } + + if (query->set_frequency) + df->frequency = query->frequency; - if (!newflags) - dt->num_enabled--; - else if (!df->flags) - dt->num_enabled++; - - df->flags = newflags; - if (newflags) - static_key_slow_inc(&df->enabled); - - if (verbose) - printk(KERN_INFO - "dfault: changed %s:%d [%s]%s #%d %s\n", - df->filename, df->lineno, - dt->mod_name, df->function, df->index, - dfault_describe_flags(df, flagbuf, - sizeof(flagbuf))); + pr_debug("changed %s:%d [%s]%s #%d %s", + df->filename, df->lineno, + dt->mod_name, df->function, df->index, + dfault_describe_flags(df, flagbuf, + sizeof(flagbuf))); } } mutex_unlock(&dfault_lock); - if (!nfound && verbose) { - printk(KERN_INFO "dfault: no matches for query\n"); - return -ENOENT; - } + pr_debug("dfault: %u matches", nfound); - return 0; + return nfound ? 0 : -ENOENT; } /* @@ -227,35 +260,10 @@ static int dfault_tokenize(char *buf, char *words[], int maxwords) buf = end; } - 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 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_number(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; -} - -/* * Parse a range. */ static inline int parse_range(char *str, @@ -267,19 +275,131 @@ static inline int parse_range(char *str, if (last_str) *last_str++ = '\0'; - if (parse_number(first_str, first) < 0) + + if (kstrtouint(first_str, 10, first)) return -EINVAL; - if (last_str != NULL) { - /* range <first>-<last> */ - if (parse_number(last_str, last) < 0) - return -EINVAL; - } else { + + if (!last_str) *last = *first; - } + else if (kstrtouint(last_str, 10, last)) + return -EINVAL; return 0; } +enum dfault_token { + TOK_INVALID, + + /* Queries */ + TOK_FUNC, + TOK_FILE, + TOK_LINE, + TOK_MODULE, + TOK_CLASS, + TOK_INDEX, + + /* Commands */ + TOK_DISABLE, + TOK_ENABLE, + TOK_ONESHOT, + TOK_FREQUENCY, +}; + +static const struct { + const char *str; + enum dfault_token tok; + unsigned args_required; +} dfault_token_strs[] = { + { "func", TOK_FUNC, 1, }, + { "file", TOK_FILE, 1, }, + { "line", TOK_LINE, 1, }, + { "module", TOK_MODULE, 1, }, + { "class", TOK_CLASS, 1, }, + { "index", TOK_INDEX, 1, }, + { "disable", TOK_DISABLE, 0, }, + { "enable", TOK_ENABLE, 0, }, + { "oneshot", TOK_ONESHOT, 0, }, + { "frequency", TOK_FREQUENCY, 1, }, +}; + +static enum dfault_token str_to_token(const char *word, unsigned nr_words) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(dfault_token_strs); i++) + if (!strcmp(word, dfault_token_strs[i].str)) { + if (nr_words < dfault_token_strs[i].args_required) { + pr_debug("insufficient arguments to \"%s\"", word); + return TOK_INVALID; + } + + return dfault_token_strs[i].tok; + } + + pr_debug("unknown keyword \"%s\"", word); + + return TOK_INVALID; +} + +static int dfault_parse_command(struct dfault_query *query, + enum dfault_token tok, + char *words[], size_t nr_words) +{ + unsigned i = 0; + int ret; + + switch (tok) { + case TOK_INVALID: + return -EINVAL; + case TOK_FUNC: + query->function = words[i++]; + case TOK_FILE: + query->filename = words[i++]; + return 1; + case TOK_LINE: + parse_range(words[i++], + &query->first_lineno, + &query->last_lineno); + break; + case TOK_MODULE: + query->module = words[i++]; + break; + case TOK_CLASS: + query->class = words[i++]; + break; + case TOK_INDEX: + parse_range(words[i++], + &query->first_index, + &query->last_index); + break; + case TOK_DISABLE: + query->set_enabled = 1; + query->enabled = DFAULT_DISABLED; + break; + case TOK_ENABLE: + query->set_enabled = 1; + query->enabled = DFAULT_ENABLED; + break; + case TOK_ONESHOT: + query->set_enabled = 1; + query->enabled = DFAULT_ONESHOT; + break; + case TOK_FREQUENCY: + query->set_frequency = 1; + ret = kstrtouint(words[i++], 10, &query->frequency); + if (ret) + return ret; + + if (!query->set_enabled) { + query->set_enabled = 1; + query->enabled = DFAULT_ENABLED; + } + break; + } + + return i; +} + /* * Parse words[] as a dfault query specification, which is a series * of (keyword, value) pairs chosen from these possibilities: @@ -293,121 +413,39 @@ static inline int parse_range(char *str, * index <m>-<n> // dynamic faults numbered from <m> * // to <n> inside each matching function */ -static int dfault_parse_query(char *words[], int nwords, - struct dfault_query *query) +static int dfault_parse_query(struct dfault_query *query, + char *words[], size_t nr_words) { - 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], "line")) { - parse_range(words[i+1], - &query->first_lineno, - &query->last_lineno); - } else if (!strcmp(words[i], "index")) { - parse_range(words[i+1], - &query->first_index, - &query->last_index); - } else { - if (verbose) - printk(KERN_ERR "%s: unknown keyword \"%s\"\n", - __func__, words[i]); - return -EINVAL; - } + unsigned i = 0; + + while (i < nr_words) { + const char *tok_str = words[i++]; + enum dfault_token tok = str_to_token(tok_str, nr_words - i); + int ret = dfault_parse_command(query, tok, words + i, + nr_words - i); + + if (ret < 0) + return ret; + i += ret; + BUG_ON(i > nr_words); } - if (verbose) - printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" " - "q->module=\"%s\" q->lineno=%u-%u\n q->index=%u-%u", - __func__, query->function, query->filename, - query->module, - query->first_lineno, query->last_lineno, - query->first_index, query->last_index); + pr_debug("q->function=\"%s\" q->filename=\"%s\" " + "q->module=\"%s\" q->lineno=%u-%u\n q->index=%u-%u", + query->function, query->filename, query->module, + query->first_lineno, query->last_lineno, + query->first_index, query->last_index); 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 _dfault's. Returns 0 on success - * or <0 on error. - */ -static int dfault_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', flag='%c'\n", __func__, - op, *str); - - for ( ; *str ; ++str) { - switch (*str) { - case 'f': - flags |= _DFAULT_ON; - break; - case 'o': - flags |= _DFAULT_ONE_SHOT; - 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_fault/conrol. Gathers the * command text from userspace, parses and executes it. */ static ssize_t dfault_proc_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { - unsigned int flags = 0, mask = 0; struct dfault_query query; #define MAXWORDS 9 int nwords; @@ -415,6 +453,8 @@ static ssize_t dfault_proc_write(struct file *file, const char __user *ubuf, char tmpbuf[256]; int ret; + memset(&query, 0, sizeof(query)); + if (len == 0) return 0; /* we don't check *offp -- multiple writes() are allowed */ @@ -423,20 +463,16 @@ static ssize_t dfault_proc_write(struct file *file, const char __user *ubuf, 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); + pr_debug("read %zu bytes from userspace", len); nwords = dfault_tokenize(tmpbuf, words, MAXWORDS); if (nwords < 0) return -EINVAL; - if (dfault_parse_query(words, nwords-1, &query)) - return -EINVAL; - if (dfault_parse_flags(words[nwords-1], &flags, &mask)) + if (dfault_parse_query(&query, words, nwords)) return -EINVAL; /* actually go and implement the change */ - ret = dfault_change(&query, flags, mask); + ret = dfault_change(&query); if (ret < 0) return ret; @@ -444,6 +480,8 @@ static ssize_t dfault_proc_write(struct file *file, const char __user *ubuf, return len; } +/* Control file read code */ + /* * Set the iterator to point to the first _dfault object * and return a pointer to that first object. Returns @@ -496,18 +534,14 @@ static void *dfault_proc_start(struct seq_file *m, loff_t *pos) struct _dfault *dp; int n = *pos; - if (verbose) - printk(KERN_INFO "%s: called m=%p *pos=%lld\n", - __func__, m, (unsigned long long)*pos); + pr_debug("m=%p *pos=%lld", m, (unsigned long long)*pos); mutex_lock(&dfault_lock); - if (!n) - return SEQ_START_TOKEN; if (n < 0) return NULL; dp = dfault_iter_first(iter); - while (dp != NULL && --n > 0) + while (dp != NULL && --n >= 0) dp = dfault_iter_next(iter); return dp; } @@ -522,9 +556,7 @@ static void *dfault_proc_next(struct seq_file *m, void *p, loff_t *pos) struct dfault_iter *iter = m->private; struct _dfault *dp; - if (verbose) - printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n", - __func__, m, p, (unsigned long long)*pos); + pr_debug("m=%p p=%p *pos=%lld", m, p, (unsigned long long)*pos); if (p == SEQ_START_TOKEN) dp = dfault_iter_first(iter); @@ -546,20 +578,14 @@ static int dfault_proc_show(struct seq_file *m, void *p) struct _dfault *df = 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 index " - "flags format\n"); - return 0; - } + pr_debug("m=%p p=%p", m, p); - seq_printf(m, "%s:%u [%s]%s %d %s \"", + seq_printf(m, "%s:%u class:%s module:%s func:%s index:%d %s \"", df->filename, df->lineno, - iter->table->mod_name, df->function, df->index, + df->class, + iter->table->mod_name, + df->function, + df->index, dfault_describe_flags(df, flagsbuf, sizeof(flagsbuf))); seq_puts(m, "\"\n"); @@ -572,9 +598,7 @@ static int dfault_proc_show(struct seq_file *m, void *p) */ static void dfault_proc_stop(struct seq_file *m, void *p) { - if (verbose) - printk(KERN_INFO "%s: called m=%p p=%p\n", - __func__, m, p); + pr_debug("m=%p p=%p", m, p); mutex_unlock(&dfault_lock); } @@ -596,8 +620,7 @@ static int dfault_proc_open(struct inode *inode, struct file *file) struct dfault_iter *iter; int err; - if (verbose) - printk(KERN_INFO "%s: called\n", __func__); + pr_debug("called"); iter = kzalloc(sizeof(*iter), GFP_KERNEL); if (iter == NULL) @@ -644,7 +667,6 @@ int dfault_add_module(struct _dfault *tab, unsigned int n, } dt->mod_name = new_name; dt->num_dfaults = n; - dt->num_enabled = 0; dt->dfaults = tab; mutex_lock(&dfault_lock); @@ -663,9 +685,7 @@ int dfault_add_module(struct _dfault *tab, unsigned int n, tab[i].index = index++; } - if (verbose) - printk(KERN_INFO "%u debug prints in module %s\n", - n, dt->mod_name); + pr_debug("%u debug prints in module %s", n, dt->mod_name); return 0; } EXPORT_SYMBOL_GPL(dfault_add_module); @@ -686,9 +706,7 @@ int dfault_remove_module(char *mod_name) struct dfault_table *dt, *nextdt; int ret = -ENOENT; - if (verbose) - printk(KERN_INFO "%s: removing module \"%s\"\n", - __func__, mod_name); + pr_debug("removing module \"%s\"", mod_name); mutex_lock(&dfault_lock); list_for_each_entry_safe(dt, nextdt, &dfault_tables, link) { |