aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bug.c')
-rw-r--r--lib/bug.c28
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 @@
47#include <linux/sched.h> 47#include <linux/sched.h>
48#include <linux/rculist.h> 48#include <linux/rculist.h>
49 49
50extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; 50extern struct bug_entry __start___bug_table[], __stop___bug_table[];
51 51
52static inline unsigned long bug_addr(const struct bug_entry *bug) 52static inline unsigned long bug_addr(const struct bug_entry *bug)
53{ 53{
@@ -62,10 +62,10 @@ static inline unsigned long bug_addr(const struct bug_entry *bug)
62/* Updates are protected by module mutex */ 62/* Updates are protected by module mutex */
63static LIST_HEAD(module_bug_list); 63static LIST_HEAD(module_bug_list);
64 64
65static const struct bug_entry *module_find_bug(unsigned long bugaddr) 65static struct bug_entry *module_find_bug(unsigned long bugaddr)
66{ 66{
67 struct module *mod; 67 struct module *mod;
68 const struct bug_entry *bug = NULL; 68 struct bug_entry *bug = NULL;
69 69
70 rcu_read_lock_sched(); 70 rcu_read_lock_sched();
71 list_for_each_entry_rcu(mod, &module_bug_list, bug_list) { 71 list_for_each_entry_rcu(mod, &module_bug_list, bug_list) {
@@ -122,15 +122,15 @@ void module_bug_cleanup(struct module *mod)
122 122
123#else 123#else
124 124
125static inline const struct bug_entry *module_find_bug(unsigned long bugaddr) 125static inline struct bug_entry *module_find_bug(unsigned long bugaddr)
126{ 126{
127 return NULL; 127 return NULL;
128} 128}
129#endif 129#endif
130 130
131const struct bug_entry *find_bug(unsigned long bugaddr) 131struct bug_entry *find_bug(unsigned long bugaddr)
132{ 132{
133 const struct bug_entry *bug; 133 struct bug_entry *bug;
134 134
135 for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) 135 for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
136 if (bugaddr == bug_addr(bug)) 136 if (bugaddr == bug_addr(bug))
@@ -141,9 +141,9 @@ const struct bug_entry *find_bug(unsigned long bugaddr)
141 141
142enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) 142enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
143{ 143{
144 const struct bug_entry *bug; 144 struct bug_entry *bug;
145 const char *file; 145 const char *file;
146 unsigned line, warning; 146 unsigned line, warning, once, done;
147 147
148 if (!is_valid_bugaddr(bugaddr)) 148 if (!is_valid_bugaddr(bugaddr))
149 return BUG_TRAP_TYPE_NONE; 149 return BUG_TRAP_TYPE_NONE;
@@ -164,6 +164,18 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
164 line = bug->line; 164 line = bug->line;
165#endif 165#endif
166 warning = (bug->flags & BUGFLAG_WARNING) != 0; 166 warning = (bug->flags & BUGFLAG_WARNING) != 0;
167 once = (bug->flags & BUGFLAG_ONCE) != 0;
168 done = (bug->flags & BUGFLAG_DONE) != 0;
169
170 if (warning && once) {
171 if (done)
172 return BUG_TRAP_TYPE_WARN;
173
174 /*
175 * Since this is the only store, concurrency is not an issue.
176 */
177 bug->flags |= BUGFLAG_DONE;
178 }
167 } 179 }
168 180
169 if (warning) { 181 if (warning) {