From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: mingo@kernel.org, rusty@rustcorp.com.au,
mathieu.desnoyers@efficios.com, oleg@redhat.com,
linux-kernel@vger.kernel.org, andi@firstfloor.org,
rostedt@goodmis.org, tglx@linutronix.de
Subject: Re: [RFC][PATCH 2/9] module: Sanitize RCU usage and locking
Date: Mon, 2 Mar 2015 11:37:06 -0800 [thread overview]
Message-ID: <20150302193706.GS15405@linux.vnet.ibm.com> (raw)
In-Reply-To: <20150228213109.952835328@infradead.org>
On Sat, Feb 28, 2015 at 10:24:49PM +0100, Peter Zijlstra wrote:
> 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().
>
> Convert everything over to RCU-sched.
>
> Furthermore add lockdep asserts to all sites, because its not at all
> clear to me the required locking is observed, esp. on exported
> functions.
>
> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Looks good -- just a couple of questions below.
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> ---
> include/linux/module.h | 12 ++++++++++--
> kernel/module.c | 42 ++++++++++++++++++++++++++++++++++--------
> lib/bug.c | 7 +++++--
> 3 files changed, 49 insertions(+), 12 deletions(-)
>
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -415,14 +415,22 @@ struct symsearch {
> bool unused;
> };
>
> -/* Search for an exported symbol by name. */
> +/*
> + * Search for an exported symbol by name.
> + *
> + * Must be called with module_mutex held or preemption disabled.
> + */
> const struct kernel_symbol *find_symbol(const char *name,
> struct module **owner,
> const unsigned long **crc,
> bool gplok,
> bool warn);
>
> -/* Walk the exported symbol table */
> +/*
> + * Walk the exported symbol table
> + *
> + * Must be called with module_mutex held or preemption disabled.
> + */
> bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
> struct module *owner,
> void *data), void *data);
> --- a/kernel/module.c
> +++ b/kernel/module.c
> @@ -106,6 +106,24 @@ static LIST_HEAD(modules);
> struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
> #endif /* CONFIG_KGDB_KDB */
>
> +static inline void module_assert_mutex(void)
> +{
> + lockdep_assert_held(&module_mutex);
> +}
> +
> +static inline void module_assert_mutex_or_preempt(void)
> +{
> +#ifdef CONFIG_LOCKDEP
> + int rcu_held = rcu_read_lock_sched_held();
> + int mutex_held = 1;
> +
> + if (debug_locks)
> + mutex_held = lockdep_is_held(&module_mutex);
> +
> + WARN_ON(!rcu_held && !mutex_held);
> +#endif
> +}
> +
> #ifdef CONFIG_MODULE_SIG
> #ifdef CONFIG_MODULE_SIG_FORCE
> static bool sig_enforce = true;
> @@ -319,6 +337,8 @@ bool each_symbol_section(bool (*fn)(cons
> #endif
> };
>
> + module_assert_mutex_or_preempt();
> +
> if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
> return true;
>
> @@ -458,6 +478,8 @@ static struct module *find_module_all(co
> {
> struct module *mod;
>
> + module_assert_mutex();
> +
> list_for_each_entry(mod, &modules, list) {
> if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
> continue;
> @@ -1856,8 +1878,8 @@ static void free_module(struct module *m
> list_del_rcu(&mod->list);
> /* Remove this module from bug list, this uses list_del_rcu */
> module_bug_cleanup(mod);
> - /* Wait for RCU synchronizing before releasing mod->list and buglist. */
> - synchronize_rcu();
> + /* Wait for RCU-sched synchronizing before releasing mod->list and buglist. */
> + synchronize_sched();
> mutex_unlock(&module_mutex);
There might be some reasons why the synchronize_sched() needs to be
within the module_mutex critical section, but safe freeing of memory
and the integrity of the list are not two of them. Doesn't hurt anything
unless someone is being very active with their modules, of course.
>
> /* This may be NULL, but that's OK */
> @@ -3106,11 +3128,11 @@ static noinline int do_init_module(struc
> mod->init_text_size = 0;
> /*
> * We want to free module_init, but be aware that kallsyms may be
> - * walking this with preempt disabled. In all the failure paths,
> - * we call synchronize_rcu/synchronize_sched, but we don't want
> - * to slow down the success path, so use actual RCU here.
> + * walking this with preempt disabled. In all the failure paths, we
> + * call synchronize_sched, but we don't want to slow down the success
> + * path, so use actual RCU here.
> */
> - call_rcu(&freeinit->rcu, do_free_init);
> + call_rcu_sched(&freeinit->rcu, do_free_init);
> mutex_unlock(&module_mutex);
> wake_up_all(&module_wq);
>
> @@ -3368,8 +3390,8 @@ static int load_module(struct load_info
> /* Unlink carefully: kallsyms could be walking list. */
> list_del_rcu(&mod->list);
> wake_up_all(&module_wq);
> - /* Wait for RCU synchronizing before releasing mod->list. */
> - synchronize_rcu();
> + /* Wait for RCU-sched synchronizing before releasing mod->list. */
> + synchronize_sched();
> mutex_unlock(&module_mutex);
Same here.
> free_module:
> /* Free lock-classes; relies on the preceding sync_rcu() */
> @@ -3636,6 +3658,8 @@ int module_kallsyms_on_each_symbol(int (
> unsigned int i;
> int ret;
>
> + module_assert_mutex();
> +
> list_for_each_entry(mod, &modules, list) {
> if (mod->state == MODULE_STATE_UNFORMED)
> continue;
> @@ -3810,6 +3834,8 @@ struct module *__module_address(unsigned
> if (addr < module_addr_min || addr > module_addr_max)
> return NULL;
>
> + module_assert_mutex_or_preempt();
> +
> list_for_each_entry_rcu(mod, &modules, list) {
> if (mod->state == MODULE_STATE_UNFORMED)
> continue;
> --- a/lib/bug.c
> +++ b/lib/bug.c
> @@ -66,7 +66,7 @@ static const struct bug_entry *module_fi
> struct module *mod;
> const struct bug_entry *bug = NULL;
>
> - rcu_read_lock();
> + rcu_read_lock_sched();
> list_for_each_entry_rcu(mod, &module_bug_list, bug_list) {
> unsigned i;
>
> @@ -77,7 +77,7 @@ static const struct bug_entry *module_fi
> }
> bug = NULL;
> out:
> - rcu_read_unlock();
> + rcu_read_unlock_sched();
>
> return bug;
> }
> @@ -88,6 +88,8 @@ void module_bug_finalize(const Elf_Ehdr
> char *secstrings;
> unsigned int i;
>
> + lockdep_assert_held(&module_mutex);
> +
> mod->bug_table = NULL;
> mod->num_bugs = 0;
>
> @@ -113,6 +115,7 @@ void module_bug_finalize(const Elf_Ehdr
>
> void module_bug_cleanup(struct module *mod)
> {
> + lockdep_assert_held(&module_mutex);
> list_del_rcu(&mod->bug_list);
> }
>
>
>
next prev parent reply other threads:[~2015-03-02 19:37 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-28 21:24 [RFC][PATCH 0/9] latched RB-trees and __module_address() Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 1/9] klp: Fix obvious RCU fail Peter Zijlstra
2015-03-01 20:09 ` Jiri Kosina
2015-03-02 8:35 ` Peter Zijlstra
2015-03-02 9:13 ` Jiri Kosina
2015-03-02 10:00 ` Peter Zijlstra
2015-03-02 9:21 ` Petr Mladek
2015-03-02 1:31 ` Masami Hiramatsu
2015-03-02 19:21 ` Paul E. McKenney
2015-03-02 21:07 ` Josh Poimboeuf
2015-02-28 21:24 ` [RFC][PATCH 2/9] module: Sanitize RCU usage and locking Peter Zijlstra
2015-03-02 11:16 ` Rusty Russell
2015-03-02 12:37 ` Peter Zijlstra
2015-03-02 19:37 ` Paul E. McKenney [this message]
2015-03-17 17:13 ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 3/9] module: Annotate module version magic Peter Zijlstra
2015-03-02 19:38 ` Paul E. McKenney
2015-02-28 21:24 ` [RFC][PATCH 4/9] module, jump_label: Fix module locking Peter Zijlstra
2015-03-02 19:39 ` Paul E. McKenney
2015-02-28 21:24 ` [RFC][PATCH 5/9] rbtree: Make lockless searches non-fatal Peter Zijlstra
2015-03-01 13:52 ` Mathieu Desnoyers
2015-03-02 8:27 ` Peter Zijlstra
2015-03-01 21:11 ` Michel Lespinasse
2015-03-02 7:46 ` Ingo Molnar
2015-03-02 8:23 ` Peter Zijlstra
2015-03-02 9:53 ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 6/9] seqlock: Better document raw_write_seqcount_latch() Peter Zijlstra
2015-03-01 14:02 ` Mathieu Desnoyers
2015-03-02 8:33 ` Peter Zijlstra
2015-03-02 8:51 ` Peter Zijlstra
2015-03-02 19:46 ` Paul E. McKenney
2015-03-01 21:12 ` Michel Lespinasse
2015-02-28 21:24 ` [RFC][PATCH 7/9] rbtree: Implement generic latch_tree Peter Zijlstra
2015-03-01 21:17 ` Michel Lespinasse
2015-03-02 8:05 ` Peter Zijlstra
2015-03-02 19:53 ` Paul E. McKenney
2015-03-17 17:24 ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 8/9] module: Optimize __module_address() using a latched RB-tree Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 9/9] module: Use __module_address() for module_address_lookup() Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150302193706.GS15405@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=andi@firstfloor.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=rusty@rustcorp.com.au \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox