rcu-tasks: Handle idle tasks for recently offlined CPUs
authorPaul E. McKenney <paulmck@kernel.org>
Wed, 25 May 2022 01:02:40 +0000 (18:02 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Mon, 20 Jun 2022 16:22:27 +0000 (09:22 -0700)
This commit identifies idle tasks for recently offlined CPUs as residing
in a quiescent state.  This is safe only because CPU-hotplug operations
are excluded during these checks.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Neeraj Upadhyay <quic_neeraju@quicinc.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: KP Singh <kpsingh@kernel.org>
kernel/rcu/tasks.h

index ec68bfe98c958c4db59d93505970b3d307931f76..414861d651964576cabaaa7e4279eab4e339132a 100644 (file)
@@ -1318,27 +1318,26 @@ static int trc_inspect_reader(struct task_struct *t, void *bhp_in)
        int nesting;
        bool ofl = cpu_is_offline(cpu);
 
-       if (task_curr(t)) {
-               WARN_ON_ONCE(ofl && !is_idle_task(t));
-
+       if (task_curr(t) && !ofl) {
                // If no chance of heavyweight readers, do it the hard way.
-               if (!ofl && !IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB))
+               if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB))
                        return -EINVAL;
 
                // If heavyweight readers are enabled on the remote task,
                // we can inspect its state despite its currently running.
                // However, we cannot safely change its state.
                n_heavy_reader_attempts++;
-               if (!ofl && // Check for "running" idle tasks on offline CPUs.
-                   !rcu_dynticks_zero_in_eqs(cpu, &t->trc_reader_nesting))
+               // Check for "running" idle tasks on offline CPUs.
+               if (!rcu_dynticks_zero_in_eqs(cpu, &t->trc_reader_nesting))
                        return -EINVAL; // No quiescent state, do it the hard way.
                n_heavy_reader_updates++;
-               if (ofl)
-                       n_heavy_reader_ofl_updates++;
                nesting = 0;
        } else {
                // The task is not running, so C-language access is safe.
                nesting = t->trc_reader_nesting;
+               WARN_ON_ONCE(ofl && task_curr(t) && !is_idle_task(t));
+               if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB) && ofl)
+                       n_heavy_reader_ofl_updates++;
        }
 
        // If not exiting a read-side critical section, mark as checked