Re: 5.10-rt: non-repeatable flush_delayed_work()...del_timer_wait_running() ATOMIC_SLEEP splat

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2020-11-01 06:23:50 [+0100], Mike Galbraith wrote:
> Apparently, timer ain't ever supposed to be running when you get there
> via flush_delayed_work(), but it was.

The first hunk will always trigger the warning and not just if the
slow/wait path is really used. The second part should fix it.

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 7edc9fba34bbd..696bb88d15db2 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1372,6 +1372,13 @@ int del_timer_sync(struct timer_list *timer)
 	 */
 	WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
 
+	/*
+	 * Can not be used with disabled interrupts on PREEMPT_RT because
+	 * del_timer_wait_running() sleeps.
+	 */
+	if (IS_ENABLED(CONFIG_PREEMPT_RT))
+		WARN_ON(irqs_disabled());
+
 	do {
 		ret = try_to_del_timer_sync(timer);
 
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c71da2a59e127..1ca03051a949f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3187,10 +3187,11 @@ EXPORT_SYMBOL_GPL(cancel_work_sync);
  */
 bool flush_delayed_work(struct delayed_work *dwork)
 {
-	local_irq_disable();
-	if (del_timer_sync(&dwork->timer))
+	if (del_timer_sync(&dwork->timer)) {
+		local_irq_disable();
 		__queue_work(dwork->cpu, dwork->wq, &dwork->work);
-	local_irq_enable();
+		local_irq_enable();
+	}
 	return flush_work(&dwork->work);
 }
 EXPORT_SYMBOL(flush_delayed_work);

Sebastian



[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux