[PATCH 1/1] rcu: fix shrink budget underflow in lazy_rcu_shrink_scan

From: Longlong Xia

Date: Mon Aug 24 2026 - 09:38:12 EST


From: Longlong Xia <xialonglong@xxxxxxxxxx>

The lazy RCU shrinker decremented sc->nr_to_scan (unsigned long)
and then tested the result with <= 0. When a single CPU's lazy
callback count exceeds the remaining budget, the subtraction wraps
to a large positive value and the <= 0 comparison, which is
equivalent to == 0 for an unsigned type, never fires again. The
scan loop then iterates through every nocb CPU instead of honouring
the reclaim budget.

Reorder the logic to compare _count against nr_to_scan before
subtracting, so the loop exits as soon as the budget is met.

Fixes: c945b4da7a448 ("rcu: Shrinker for lazy rcu")
Assisted-by: Zcode:GLM-5.2
Signed-off-by: Longlong Xia <xialonglong@xxxxxxxxxx>
---
kernel/rcu/tree_nocb.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index 19bb42672baf..afc3ab84cc47 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -1332,10 +1332,11 @@ lazy_rcu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
rcu_nocb_try_flush_bypass(rdp, jiffies);
rcu_nocb_unlock_irqrestore(rdp, flags);
wake_nocb_gp(rdp);
- sc->nr_to_scan -= _count;
count += _count;
- if (sc->nr_to_scan <= 0)
+
+ if (_count >= sc->nr_to_scan)
break;
+ sc->nr_to_scan -= _count;
}

mutex_unlock(&rcu_state.nocb_mutex);
--
2.43.0