Skip to content

Commit 3a4a036

Browse files
committed
Merge tag 'rcu.fixes.6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux
Pull RCU fix from Neeraj Upadhyay: "Fix a regression introduced by commit b41642c ("rcu: Fix rcu_read_unlock() deadloop due to IRQ work") which results in boot hang as reported by kernel test bot at [1]. This issue happens because RCU re-initializes the deferred QS IRQ work everytime it is queued. With commit b41642c, the IRQ work re-initialization can happen while it is already queued. This results in IRQ work being requeued to itself. When IRQ work finally fires, as it is requeued to itself, it is repeatedly executed and results in hang. Fix this with initializing the IRQ work only once before the CPU boots" Link: https://lore.kernel.org/rcu/[email protected]/ [1] * tag 'rcu.fixes.6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux: rcu: Fix racy re-initialization of irq_work causing hangs
2 parents 91325f3 + 61399e0 commit 3a4a036

File tree

3 files changed

+9
-2
lines changed

3 files changed

+9
-2
lines changed

kernel/rcu/tree.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4262,6 +4262,8 @@ int rcutree_prepare_cpu(unsigned int cpu)
42624262
rdp->rcu_iw_gp_seq = rdp->gp_seq - 1;
42634263
trace_rcu_grace_period(rcu_state.name, rdp->gp_seq, TPS("cpuonl"));
42644264
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
4265+
4266+
rcu_preempt_deferred_qs_init(rdp);
42654267
rcu_spawn_rnp_kthreads(rnp);
42664268
rcu_spawn_cpu_nocb_kthread(cpu);
42674269
ASSERT_EXCLUSIVE_WRITER(rcu_state.n_online_cpus);

kernel/rcu/tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp);
488488
static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
489489
static void rcu_flavor_sched_clock_irq(int user);
490490
static void dump_blkd_tasks(struct rcu_node *rnp, int ncheck);
491+
static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp);
491492
static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
492493
static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
493494
static bool rcu_is_callbacks_kthread(struct rcu_data *rdp);

kernel/rcu/tree_plugin.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,6 @@ static void rcu_read_unlock_special(struct task_struct *t)
763763
cpu_online(rdp->cpu)) {
764764
// Get scheduler to re-evaluate and call hooks.
765765
// If !IRQ_WORK, FQS scan will eventually IPI.
766-
rdp->defer_qs_iw =
767-
IRQ_WORK_INIT_HARD(rcu_preempt_deferred_qs_handler);
768766
rdp->defer_qs_iw_pending = DEFER_QS_PENDING;
769767
irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);
770768
}
@@ -904,6 +902,10 @@ dump_blkd_tasks(struct rcu_node *rnp, int ncheck)
904902
}
905903
}
906904

905+
static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp)
906+
{
907+
rdp->defer_qs_iw = IRQ_WORK_INIT_HARD(rcu_preempt_deferred_qs_handler);
908+
}
907909
#else /* #ifdef CONFIG_PREEMPT_RCU */
908910

909911
/*
@@ -1103,6 +1105,8 @@ dump_blkd_tasks(struct rcu_node *rnp, int ncheck)
11031105
WARN_ON_ONCE(!list_empty(&rnp->blkd_tasks));
11041106
}
11051107

1108+
static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp) { }
1109+
11061110
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
11071111

11081112
/*

0 commit comments

Comments
 (0)