diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2015-05-26 21:39:35 -0400 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-05-27 22:01:52 -0400 |
| commit | 0be964be0d45084245673c971d72a4b51690231d (patch) | |
| tree | c3d0f0497d325c28f344adda9c3305e75e550c60 /lib | |
| parent | bed831f9a251968272dae10a83b512c7db256ef0 (diff) | |
module: Sanitize RCU usage and locking
Currently the RCU usage in module is an inconsistent mess of RCU and
RCU-sched, this is broken for CONFIG_PREEMPT where synchronize_rcu()
does not imply synchronize_sched().
Most usage sites use preempt_{dis,en}able() which is RCU-sched, but
(most of) the modification sites use synchronize_rcu(). With the
exception of the module bug list, which actually uses RCU.
Convert everything over to RCU-sched.
Furthermore add lockdep asserts to all sites, because it's not at all
clear to me the required locking is observed, esp. on exported
functions.
Cc: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/bug.c | 7 |
1 files changed, 5 insertions, 2 deletions
| @@ -66,7 +66,7 @@ static const struct bug_entry *module_find_bug(unsigned long bugaddr) | |||
| 66 | struct module *mod; | 66 | struct module *mod; |
| 67 | const struct bug_entry *bug = NULL; | 67 | const struct bug_entry *bug = NULL; |
| 68 | 68 | ||
| 69 | rcu_read_lock(); | 69 | rcu_read_lock_sched(); |
| 70 | list_for_each_entry_rcu(mod, &module_bug_list, bug_list) { | 70 | list_for_each_entry_rcu(mod, &module_bug_list, bug_list) { |
| 71 | unsigned i; | 71 | unsigned i; |
| 72 | 72 | ||
| @@ -77,7 +77,7 @@ static const struct bug_entry *module_find_bug(unsigned long bugaddr) | |||
| 77 | } | 77 | } |
| 78 | bug = NULL; | 78 | bug = NULL; |
| 79 | out: | 79 | out: |
| 80 | rcu_read_unlock(); | 80 | rcu_read_unlock_sched(); |
| 81 | 81 | ||
| 82 | return bug; | 82 | return bug; |
| 83 | } | 83 | } |
| @@ -88,6 +88,8 @@ void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | |||
| 88 | char *secstrings; | 88 | char *secstrings; |
| 89 | unsigned int i; | 89 | unsigned int i; |
| 90 | 90 | ||
| 91 | lockdep_assert_held(&module_mutex); | ||
| 92 | |||
| 91 | mod->bug_table = NULL; | 93 | mod->bug_table = NULL; |
| 92 | mod->num_bugs = 0; | 94 | mod->num_bugs = 0; |
| 93 | 95 | ||
| @@ -113,6 +115,7 @@ void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | |||
| 113 | 115 | ||
| 114 | void module_bug_cleanup(struct module *mod) | 116 | void module_bug_cleanup(struct module *mod) |
| 115 | { | 117 | { |
| 118 | lockdep_assert_held(&module_mutex); | ||
| 116 | list_del_rcu(&mod->bug_list); | 119 | list_del_rcu(&mod->bug_list); |
| 117 | } | 120 | } |
| 118 | 121 | ||
