From 27eacb9d72679d590271b2d3e9da2a77e4f60317 Mon Sep 17 00:00:00 2001 From: Guoju Fang Date: Fri, 18 Feb 2022 11:18:45 +0800 Subject: [PATCH] net: sched: add barrier to fix packet stuck problem for lockless qdisc The commit a90c57f2cedd ("net: sched: fix packet stuck problem for lockless qdisc") and commit 89837eb4b246 ("net: sched: add barrier to ensure correct ordering for lockless qdisc") fix a packet stuck problem for lockless qdisc and describe the race condition. But after the two commits we still can reproduce a similar problem, and one more barrier is needed to fix it. Now the concurrent operations can be described as below, CPU0 | CPU1 qdisc_run_end() | qdisc_run_begin() . | . spin_unlock() | set_bit() . | smp_mb__after_atomic() test_bit() | spin_trylock() . | . In qdisc_run_end(), the spin_unlock() only has store-release semantic, which guarantees all earlier memory access are visible before the spin_unlock(), but the subsequent test_bit() may be reordered to precede the it. So one explicit barrier is needed between spin_unlock() and test_bit() to ensure the correct order. Signed-off-by: Guoju Fang --- include/net/sch_generic.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 472843eedbae..ff843e2a4544 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -229,6 +229,9 @@ static inline void qdisc_run_end(struct Qdisc *qdisc) if (qdisc->flags & TCQ_F_NOLOCK) { spin_unlock(&qdisc->seqlock); + /* store-load barrier */ + smp_mb(); + if (unlikely(test_bit(__QDISC_STATE_MISSED, &qdisc->state))) __netif_schedule(qdisc); -- 2.32.0.3.g01195cf9f