bpf: report RCU QS in cpumap kthread
authorYan Zhai <yan@cloudflare.com>
Tue, 19 Mar 2024 20:44:40 +0000 (13:44 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 21 Mar 2024 04:05:43 +0000 (21:05 -0700)
When there are heavy load, cpumap kernel threads can be busy polling
packets from redirect queues and block out RCU tasks from reaching
quiescent states. It is insufficient to just call cond_resched() in such
context. Periodically raise a consolidated RCU QS before cond_resched
fixes the problem.

Fixes: 6710e1126934 ("bpf: introduce new bpf cpu map type BPF_MAP_TYPE_CPUMAP")
Reviewed-by: Jesper Dangaard Brouer <hawk@kernel.org>
Signed-off-by: Yan Zhai <yan@cloudflare.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
Link: https://lore.kernel.org/r/c17b9f1517e19d813da3ede5ed33ee18496bb5d8.1710877680.git.yan@cloudflare.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
kernel/bpf/cpumap.c

index 9ee8da4774656716718909d2c7d93362d9313ecd..a8e34416e960f5c89d90e0e2981154aa206bac42 100644 (file)
@@ -263,6 +263,7 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
 static int cpu_map_kthread_run(void *data)
 {
        struct bpf_cpu_map_entry *rcpu = data;
+       unsigned long last_qs = jiffies;
 
        complete(&rcpu->kthread_running);
        set_current_state(TASK_INTERRUPTIBLE);
@@ -288,10 +289,12 @@ static int cpu_map_kthread_run(void *data)
                        if (__ptr_ring_empty(rcpu->queue)) {
                                schedule();
                                sched = 1;
+                               last_qs = jiffies;
                        } else {
                                __set_current_state(TASK_RUNNING);
                        }
                } else {
+                       rcu_softirq_qs_periodic(last_qs);
                        sched = cond_resched();
                }