Skip to content

Commit

Permalink
rcu: Keep synchronize_rcu() from enabling irqs in early boot
Browse files Browse the repository at this point in the history
Making polled RCU grace periods account for expedited grace periods
required acquiring the leaf rcu_node structure's lock during early boot,
but after rcu_init() was called.  This lock is irq-disabled, but the
code incorrectly assumes that irqs are always disabled when invoking
synchronize_rcu().  The exception is early boot before the scheduler has
started, which means that upon return from synchronize_rcu(), irqs will
be incorrectly enabled.

This commit fixes this bug by using irqsave/irqrestore locking primitives.

Fixes: bf95b2b ("rcu: Switch polled grace-period APIs to ->gp_seq_polled")

Reported-by: Steven Rostedt <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
  • Loading branch information
paulmckrcu committed Oct 20, 2022
1 parent 9abf231 commit 31d8aaa
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions kernel/rcu/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1403,30 +1403,32 @@ static void rcu_poll_gp_seq_end(unsigned long *snap)
// where caller does not hold the root rcu_node structure's lock.
static void rcu_poll_gp_seq_start_unlocked(unsigned long *snap)
{
unsigned long flags;
struct rcu_node *rnp = rcu_get_root();

if (rcu_init_invoked()) {
lockdep_assert_irqs_enabled();
raw_spin_lock_irq_rcu_node(rnp);
raw_spin_lock_irqsave_rcu_node(rnp, flags);
}
rcu_poll_gp_seq_start(snap);
if (rcu_init_invoked())
raw_spin_unlock_irq_rcu_node(rnp);
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
}

// Make the polled API aware of the end of a grace period, but where
// caller does not hold the root rcu_node structure's lock.
static void rcu_poll_gp_seq_end_unlocked(unsigned long *snap)
{
unsigned long flags;
struct rcu_node *rnp = rcu_get_root();

if (rcu_init_invoked()) {
lockdep_assert_irqs_enabled();
raw_spin_lock_irq_rcu_node(rnp);
raw_spin_lock_irqsave_rcu_node(rnp, flags);
}
rcu_poll_gp_seq_end(snap);
if (rcu_init_invoked())
raw_spin_unlock_irq_rcu_node(rnp);
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
}

/*
Expand Down

0 comments on commit 31d8aaa

Please sign in to comment.