diff options
Diffstat (limited to 'lib/bug.c')
| -rw-r--r-- | lib/bug.c | 28 | 
1 files changed, 20 insertions, 8 deletions
| diff --git a/lib/bug.c b/lib/bug.c index 06edbbef0623..a6a1137d06db 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -47,7 +47,7 @@  #include <linux/sched.h>  #include <linux/rculist.h> -extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; +extern struct bug_entry __start___bug_table[], __stop___bug_table[];  static inline unsigned long bug_addr(const struct bug_entry *bug)  { @@ -62,10 +62,10 @@ static inline unsigned long bug_addr(const struct bug_entry *bug)  /* Updates are protected by module mutex */  static LIST_HEAD(module_bug_list); -static const struct bug_entry *module_find_bug(unsigned long bugaddr) +static struct bug_entry *module_find_bug(unsigned long bugaddr)  {  	struct module *mod; -	const struct bug_entry *bug = NULL; +	struct bug_entry *bug = NULL;  	rcu_read_lock_sched();  	list_for_each_entry_rcu(mod, &module_bug_list, bug_list) { @@ -122,15 +122,15 @@ void module_bug_cleanup(struct module *mod)  #else -static inline const struct bug_entry *module_find_bug(unsigned long bugaddr) +static inline struct bug_entry *module_find_bug(unsigned long bugaddr)  {  	return NULL;  }  #endif -const struct bug_entry *find_bug(unsigned long bugaddr) +struct bug_entry *find_bug(unsigned long bugaddr)  { -	const struct bug_entry *bug; +	struct bug_entry *bug;  	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)  		if (bugaddr == bug_addr(bug)) @@ -141,9 +141,9 @@ const struct bug_entry *find_bug(unsigned long bugaddr)  enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)  { -	const struct bug_entry *bug; +	struct bug_entry *bug;  	const char *file; -	unsigned line, warning; +	unsigned line, warning, once, done;  	if (!is_valid_bugaddr(bugaddr))  		return BUG_TRAP_TYPE_NONE; @@ -164,6 +164,18 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)  		line = bug->line;  #endif  		warning = (bug->flags & BUGFLAG_WARNING) != 0; +		once = (bug->flags & BUGFLAG_ONCE) != 0; +		done = (bug->flags & BUGFLAG_DONE) != 0; + +		if (warning && once) { +			if (done) +				return BUG_TRAP_TYPE_WARN; + +			/* +			 * Since this is the only store, concurrency is not an issue. +			 */ +			bug->flags |= BUGFLAG_DONE; +		}  	}  	if (warning) { | 
