Messages in this thread | | | Date | Fri, 9 Apr 2021 13:05:10 -0700 | From | "Paul E. McKenney" <> | Subject | Re: [PATCH 2/5] srcu: Initialize SRCU after timers |
| |
On Fri, Apr 09, 2021 at 12:38:59AM +0200, Frederic Weisbecker wrote: > Once srcu_init() is called, the SRCU core is free to queue delayed > workqueues, which rely on timers. However init_timers() is called > several steps after rcu_init(). Any call_srcu() in-between would finish > its course inside a dangerously uninitialized timer core. > > Make sure we stay in early SRCU mode until everything is well settled. > > Signed-off-by: Frederic Weisbecker <frederic@kernel.org> > Cc: Uladzislau Rezki <urezki@gmail.com> > Cc: Boqun Feng <boqun.feng@gmail.com> > Cc: Lai Jiangshan <jiangshanlai@gmail.com> > Cc: Neeraj Upadhyay <neeraju@codeaurora.org> > Cc: Josh Triplett <josh@joshtriplett.org> > Cc: Joel Fernandes <joel@joelfernandes.org>
Good catches! Apparently not so many people are using SRCU that early in boot, but good to get it working. I queued this patch and the preceding one (1/5).
Thanx, Paul
> --- > include/linux/srcu.h | 6 ++++++ > init/main.c | 2 ++ > kernel/rcu/rcu.h | 6 ------ > kernel/rcu/srcutree.c | 5 +++++ > kernel/rcu/tiny.c | 1 - > kernel/rcu/tree.c | 1 - > 6 files changed, 13 insertions(+), 8 deletions(-) > > diff --git a/include/linux/srcu.h b/include/linux/srcu.h > index a0895bbf71ce..e6011a9975af 100644 > --- a/include/linux/srcu.h > +++ b/include/linux/srcu.h > @@ -64,6 +64,12 @@ unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp); > unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp); > bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie); > > +#ifdef CONFIG_SRCU > +void srcu_init(void); > +#else /* #ifdef CONFIG_SRCU */ > +static inline void srcu_init(void) { } > +#endif /* #else #ifdef CONFIG_SRCU */ > + > #ifdef CONFIG_DEBUG_LOCK_ALLOC > > /** > diff --git a/init/main.c b/init/main.c > index 53b278845b88..1bc5cc9e52ef 100644 > --- a/init/main.c > +++ b/init/main.c > @@ -42,6 +42,7 @@ > #include <linux/profile.h> > #include <linux/kfence.h> > #include <linux/rcupdate.h> > +#include <linux/srcu.h> > #include <linux/moduleparam.h> > #include <linux/kallsyms.h> > #include <linux/writeback.h> > @@ -956,6 +957,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) > tick_init(); > rcu_init_nohz(); > init_timers(); > + srcu_init(); > hrtimers_init(); > softirq_init(); > timekeeping_init(); > diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h > index d64b842f4078..b3af34068051 100644 > --- a/kernel/rcu/rcu.h > +++ b/kernel/rcu/rcu.h > @@ -422,12 +422,6 @@ do { \ > > #endif /* #if defined(CONFIG_SRCU) || !defined(CONFIG_TINY_RCU) */ > > -#ifdef CONFIG_SRCU > -void srcu_init(void); > -#else /* #ifdef CONFIG_SRCU */ > -static inline void srcu_init(void) { } > -#endif /* #else #ifdef CONFIG_SRCU */ > - > #ifdef CONFIG_TINY_RCU > /* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */ > static inline bool rcu_gp_is_normal(void) { return true; } > diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c > index 10e681ea7051..108f9ca06047 100644 > --- a/kernel/rcu/srcutree.c > +++ b/kernel/rcu/srcutree.c > @@ -1384,6 +1384,11 @@ void __init srcu_init(void) > { > struct srcu_struct *ssp; > > + /* > + * Once that is set, call_srcu() can follow the normal path and > + * queue delayed work. This must follow RCU workqueues creation > + * and timers initialization. > + */ > srcu_init_done = true; > while (!list_empty(&srcu_boot_list)) { > ssp = list_first_entry(&srcu_boot_list, struct srcu_struct, > diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c > index c8a029fbb114..340b3f8b090d 100644 > --- a/kernel/rcu/tiny.c > +++ b/kernel/rcu/tiny.c > @@ -221,5 +221,4 @@ void __init rcu_init(void) > { > open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); > rcu_early_boot_tests(); > - srcu_init(); > } > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c > index 5c214705c33f..740f5cd34459 100644 > --- a/kernel/rcu/tree.c > +++ b/kernel/rcu/tree.c > @@ -4714,7 +4714,6 @@ void __init rcu_init(void) > WARN_ON(!rcu_gp_wq); > rcu_par_gp_wq = alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); > WARN_ON(!rcu_par_gp_wq); > - srcu_init(); > > /* Fill in default value for rcutree.qovld boot parameter. */ > /* -After- the rcu_node ->lock fields are initialized! */ > -- > 2.25.1 >
| |