mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
Merge: rcu: Fix rcu_read_unlock() deadloop due to softirq
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/2851 JIRA: https://issues.redhat.com/browse/RHEL-178446 There is a deadloop in rcu_read_unlock() that can be hit by ftrace (in particular while running the LTP ftrace-stress-test). When this happened, other processes get stuck in softlockup. Signed-off-by: Jerome Marchand <jmarchan@redhat.com> Approved-by: Phil Auld <pauld@redhat.com> Approved-by: Waiman Long <longman@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
+1
-1
@@ -203,7 +203,7 @@ struct rcu_data {
|
||||
/* during and after the last grace */
|
||||
/* period it is aware of. */
|
||||
struct irq_work defer_qs_iw; /* Obtain later scheduler attention. */
|
||||
int defer_qs_iw_pending; /* Scheduler attention pending? */
|
||||
int defer_qs_pending; /* irqwork or softirq pending? */
|
||||
struct work_struct strict_work; /* Schedule readers for strict GPs. */
|
||||
|
||||
/* 2) batch handling */
|
||||
|
||||
@@ -487,8 +487,8 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
|
||||
union rcu_special special;
|
||||
|
||||
rdp = this_cpu_ptr(&rcu_data);
|
||||
if (rdp->defer_qs_iw_pending == DEFER_QS_PENDING)
|
||||
rdp->defer_qs_iw_pending = DEFER_QS_IDLE;
|
||||
if (rdp->defer_qs_pending == DEFER_QS_PENDING)
|
||||
rdp->defer_qs_pending = DEFER_QS_IDLE;
|
||||
|
||||
/*
|
||||
* If RCU core is waiting for this CPU to exit its critical section,
|
||||
@@ -646,7 +646,7 @@ static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp)
|
||||
* 5. Deferred QS reporting does not happen.
|
||||
*/
|
||||
if (rcu_preempt_depth() > 0)
|
||||
WRITE_ONCE(rdp->defer_qs_iw_pending, DEFER_QS_IDLE);
|
||||
WRITE_ONCE(rdp->defer_qs_pending, DEFER_QS_IDLE);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
@@ -750,7 +750,10 @@ static void rcu_read_unlock_special(struct task_struct *t)
|
||||
// Using softirq, safe to awaken, and either the
|
||||
// wakeup is free or there is either an expedited
|
||||
// GP in flight or a potential need to deboost.
|
||||
if (rdp->defer_qs_pending != DEFER_QS_PENDING) {
|
||||
rdp->defer_qs_pending = DEFER_QS_PENDING;
|
||||
raise_softirq_irqoff(RCU_SOFTIRQ);
|
||||
}
|
||||
} else {
|
||||
// Enabling BH or preempt does reschedule, so...
|
||||
// Also if no expediting and no possible deboosting,
|
||||
@@ -759,11 +762,11 @@ static void rcu_read_unlock_special(struct task_struct *t)
|
||||
set_tsk_need_resched(current);
|
||||
set_preempt_need_resched();
|
||||
if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled &&
|
||||
needs_exp && rdp->defer_qs_iw_pending != DEFER_QS_PENDING &&
|
||||
needs_exp && rdp->defer_qs_pending != DEFER_QS_PENDING &&
|
||||
cpu_online(rdp->cpu)) {
|
||||
// Get scheduler to re-evaluate and call hooks.
|
||||
// If !IRQ_WORK, FQS scan will eventually IPI.
|
||||
rdp->defer_qs_iw_pending = DEFER_QS_PENDING;
|
||||
rdp->defer_qs_pending = DEFER_QS_PENDING;
|
||||
irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user