Skip to contentSkip to conversation

FAILED: patch "[PATCH] tick/nohz_full: Don't abuse smp_call_function_single() in" failed to apply to 5.10-stable tree

PATCH [email protected] 1 participant 1 message Jun 17, 2024

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 07c54cc5988f19c9642fd463c2dbdac7fc52f777
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024061708-stratus-crewless-b283@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..

Possible dependencies:

07c54cc5988f ("tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()") f87cbcb345d0 ("timekeeping: Use READ/WRITE_ONCE() for tick_do_timer_cpu")
a478ffb2ae23 ("tick: Move individual bit features to debuggable mask accesses") 3ce74f1a8566 ("tick: Move got_idle_tick away from common flags")
3ad6eb0683a1 ("tick: Start centralizing tick related CPU hotplug operations")
3650f49bfb95 ("tick/sched: Rename tick_nohz_stop_sched_tick() to tick_nohz_full_stop_tick()") 27dc08096ce4 ("tick: Use IS_ENABLED() whenever possible")
37263ba0c44b ("tick/nohz: Remove duplicate between lowres and highres handlers") ffb7e01c4e65 ("tick/nohz: Remove duplicate between tick_nohz_switch_to_nohz() and tick_setup_sched_timer()") 4c532939aa2e ("tick/sched: Split out jiffies update helper function")
73129cf4b69c ("timers: Optimization for timer_base_try_to_set_idle()")
e2e1d724e948 ("timers: Move marking timer bases idle into tick_nohz_stop_tick()") 39ed699fb660 ("timers: Split out get next timer interrupt")
bebed6649e85 ("timers: Restructure get_next_timer_interrupt()")
f365d0550615 ("tick/sched: Add function description for tick_nohz_next_event()") da65f29dada7 ("timers: Fix nextevt calculation when no timers are pending")
bb8caad5083f ("timers: Rework idle logic")
7a39a5080ef0 ("timers: Use already existing function for forwarding timer base") b5e6f59888c7 ("timers: Move store of next event into __next_timer_interrupt()") b573c73101d8 ("tracing/timers: Add tracepoint for tracking timer base is_idle flag")

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 07c54cc5988f19c9642fd463c2dbdac7fc52f777 Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <[email protected]>
Date: Tue, 28 May 2024 14:20:19 +0200
Subject: [PATCH] tick/nohz_full: Don't abuse smp_call_function_single() in
tick_setup_device()

After the recent commit 5097cbcb38e6 ("sched/isolation: Prevent boot crash when the boot CPU is nohz_full") the kernel no longer crashes, but there is another problem.

In this case tick_setup_device() calls tick_take_do_timer_from_boot() to update tick_do_timer_cpu and this triggers the WARN_ON_ONCE(irqs_disabled) in smp_call_function_single().

Kill tick_take_do_timer_from_boot() and just use WRITE_ONCE(), the new comment explains why this is safe (thanks Thomas!).

kernel/time/tick-common.c +14 -28
index d88b13076b79..a47bcf71defc 100644
@@ -178,26 +178,6 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
 	}
 }
 
-#ifdef CONFIG_NO_HZ_FULL
-static void giveup_do_timer(void *info)
-{
-	int cpu = *(unsigned int *)info;
-
-	WARN_ON(tick_do_timer_cpu != smp_processor_id());
-
-	tick_do_timer_cpu = cpu;
-}
-
-static void tick_take_do_timer_from_boot(void)
-{
-	int cpu = smp_processor_id();
-	int from = tick_do_timer_boot_cpu;
-
-	if (from >= 0 && from != cpu)
-		smp_call_function_single(from, giveup_do_timer, &cpu, 1);
-}
-#endif
-
 /*
  * Setup the tick device
  */
@@ -221,19 +201,25 @@ static void tick_setup_device(struct tick_device *td,
 			tick_next_period = ktime_get();
 #ifdef CONFIG_NO_HZ_FULL
 			/*
-			 * The boot CPU may be nohz_full, in which case set
-			 * tick_do_timer_boot_cpu so the first housekeeping
-			 * secondary that comes up will take do_timer from
-			 * us.
+			 * The boot CPU may be nohz_full, in which case the
+			 * first housekeeping secondary will take do_timer()
+			 * from it.
 			 */
 			if (tick_nohz_full_cpu(cpu))
 				tick_do_timer_boot_cpu = cpu;
 
-		} else if (tick_do_timer_boot_cpu != -1 &&
-						!tick_nohz_full_cpu(cpu)) {
-			tick_take_do_timer_from_boot();
+		} else if (tick_do_timer_boot_cpu != -1 && !tick_nohz_full_cpu(cpu)) {
 			tick_do_timer_boot_cpu = -1;
-			WARN_ON(READ_ONCE(tick_do_timer_cpu) != cpu);
+			/*
+			 * The boot CPU will stay in periodic (NOHZ disabled)
+			 * mode until clocksource_done_booting() called after
+			 * smp_init() selects a high resolution clocksource and
+			 * timekeeping_notify() kicks the NOHZ stuff alive.
+			 *
+			 * So this WRITE_ONCE can only race with the READ_ONCE
+			 * check in tick_periodic() but this race is harmless.
+			 */
+			WRITE_ONCE(tick_do_timer_cpu, cpu);
 #endif
 		}