From: sashiko-bot@kernel.org
To: "Yafang Shao" <laoar.shao@gmail.com>
Cc: tj@kernel.org, mkoutny@suse.com, hannes@cmpxchg.org, bpf@vger.kernel.org
Subject: Re: [RFC PATCH v2 2/3] sched: add per-cgroup NUMA balancing mode selection via BPF
Date: Mon, 12 Oct 2026 12:25:52 +0000 [thread overview]
Message-ID: <sashiko-outbox-168093@kernel.org> (raw)
In-Reply-To: <20261012120438.52849-3-laoar.shao@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] mm: folio_can_map_prot_numa() disables NORMAL NUMA balancing on top-tier nodes when TIERING is active
- [High] sched: AB-BA deadlock in bpf_numab_mode (rq->lock -> pi_lock)
- [High] bpf: missing __nullable annotation in bpf_numab_ops leads to kernel panic
- [Medium] sched: BPF NUMA balancing opt-in ignored by LLC scheduling
--
commit 3975a69bbe7653d443a34c5ce6984dadc110d558
Author: Yafang Shao <laoar.shao@gmail.com>
sched: add per-cgroup NUMA balancing mode selection via BPF
Global NUMA balancing is all-or-nothing: kernel.numa_balancing and
kernel.numa_balancing_mode pick the mode for every workload. A
latency-sensitive service wants the scheduler's NUMA statistics but
not tiering's promotion machinery. This patch adds a bpf_numab_ops
struct_ops to allow policies attached to a cgroup to pick a mode.
> diff --git a/include/linux/bpf_numab.h b/include/linux/bpf_numab.h
> --- /dev/null
> +++ b/include/linux/bpf_numab.h
[ ... ]
> +struct bpf_numab_ops {
> + /**
> + * numab_mode - request a NUMA balancing mode
> + * @p: task the NUMA balancing machinery is about to act on, or NULL
> + * @folio: folio whose NUMA balancing semantics are being decided,
> + * or NULL
> + *
> + * Exactly one of @p and @folio is set. The kernel passes @p when
[ ... ]
> + * Return: bits from enum bpf_numab_mode. Other bits are dropped.
> + */
> + u32 (*numab_mode)(struct task_struct *p, struct folio *folio);
[Severity: High]
Could the lack of a __nullable annotation here lead to a NULL pointer
dereference in user BPF programs?
The BPF verifier relies on the __nullable suffix on struct_ops stub
arguments to mark them as PTR_MAYBE_NULL. Without it, the verifier assumes
they are strictly non-NULL and optimizes away any user-provided NULL checks.
When the kernel passes a NULL argument (as designed, since only one of p or
folio is set), the executing BPF program will crash the system.
> +};
[ ... ]
> diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/numa_balancing.h
> --- a/include/linux/sched/numa_balancing.h
> +++ b/include/linux/sched/numa_balancing.h
[ ... ]
> static inline bool task_numab_enabled(struct task_struct *p)
> {
> + u32 state = bpf_numab_mode(p, NULL);
> +
> + /* A policy can always opt out, regardless of the global state. */
> + if (state & BPF_NUMAB_DISABLED)
> + return false;
> + if (state & (BPF_NUMAB_NORMAL | BPF_NUMAB_TIERING))
> + return true;
> return static_branch_unlikely(&sched_numa_balancing);
> }
[Severity: Medium]
Is this BPF opt-in overlooked by the LLC scheduling logic?
This new helper allows workloads to opt into NUMA balancing even when global
NUMA balancing is disabled. However, functions like get_pref_llc() and
get_scan_cpumasks() still check the global static key sched_numa_balancing
directly instead of using task_numab_enabled(p). For a workload that
explicitly opts in via BPF, its numa_preferred_nid and CPU scan masks will
be skipped.
[ ... ]
> diff --git a/kernel/sched/bpf_numab.c b/kernel/sched/bpf_numab.c
> --- /dev/null
> +++ b/kernel/sched/bpf_numab.c
[ ... ]
> +static u32 numab_mode_stub(struct task_struct *p, struct folio *folio)
> +{
> + return BPF_NUMAB_GLOBAL;
> +}
[Severity: High]
Should this stub function also include the __nullable suffix on its
arguments?
As mentioned in include/linux/bpf_numab.h, omitting the __nullable suffix
(e.g., p__nullable) prevents the verifier from recognizing the arguments as
optional. This leads to dead-code elimination of user NULL checks and a
subsequent system crash.
[ ... ]
> +u32 bpf_numab_mode(struct task_struct *p, struct folio *folio)
> +{
[ ... ]
> + bpf_cgroup_struct_ops_foreach(ops, item, cgrp, CGROUP_NUMAB_OPS) {
> + if (ops->numab_mode)
> + acc |= ops->numab_mode(p, folio) & BPF_NUMAB_VALID_MASK;
> + }
> +
> + cgroup_bpf_put(cgrp);
[Severity: High]
Could dropping the cgroup BPF reference here trigger an AB-BA deadlock?
The scheduler path calls task_tick_fair() under rq->lock, which invokes
bpf_numab_mode(). Dropping the cgroup BPF reference here via
cgroup_bpf_put() can trigger queue_work() if this is the final reference
while the cgroup is being offlined.
queue_work() acquires pool->lock and wakes up a worker by acquiring its
pi_lock. Because standard wakeup paths acquire pi_lock before rq->lock, this
inverted rq->lock -> pool->lock -> pi_lock sequence leads to a deadlock.
Since this code is already protected by rcu_read_lock(), is the reference
counting strictly necessary here?
> +out:
> + rcu_read_unlock();
> + return acc;
> +}
[ ... ]
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -884,11 +884,10 @@ bool folio_can_map_prot_numa(struct folio *folio, struct vm_area_struct *vma,
> return false;
>
> /*
> - * Skip scanning top tier node if normal numa
> - * balancing is disabled
> + * Skip scanning top tier memory whose owner participates in
> + * tiering: hinting faults on it would buy nothing.
> */
> - if (!(sysctl_numa_balancing_mode & NUMA_BALANCING_NORMAL) &&
> - node_is_toptier(nid))
> + if (folio_numab_mode_tiering(folio) && node_is_toptier(nid))
> return false;
[Severity: High]
Does this unconditionally disable NORMAL NUMA balancing on top-tier nodes
when TIERING is active?
Previously, this skipped hinting faults on top-tier nodes only if
NUMA_BALANCING_NORMAL was explicitly disabled. The new logic skips top-tier
scanning entirely if tiering is enabled.
When the global sysctl_numa_balancing_mode is 3 (both NORMAL and TIERING
enabled), folio_numab_mode_tiering() returns true. This breaks standard NUMA
page placement optimization for fast memory on tiered systems by dropping
all top-tier scanning.
>
> if (folio_use_access_time(folio))
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012120438.52849-1-laoar.shao@gmail.com?part=2
next prev parent reply other threads:[~2026-10-12 12:25 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 12:04 [RFC PATCH v2 0/3] BPF-based per-cgroup NUMA balancing mode selection Yafang Shao
2026-10-12 12:04 ` [RFC PATCH v2 1/3] sched: add helpers for numa balancing Yafang Shao
2026-10-12 12:19 ` sashiko-bot
2026-10-12 14:23 ` Yafang Shao
2026-10-13 7:38 ` David Hildenbrand (Arm)
2026-10-13 9:14 ` Yafang Shao
2026-10-12 12:04 ` [RFC PATCH v2 2/3] sched: add per-cgroup NUMA balancing mode selection via BPF Yafang Shao
2026-10-12 12:25 ` sashiko-bot [this message]
2026-10-12 13:55 ` Yafang Shao
2026-10-12 12:04 ` [RFC PATCH v2 3/3] selftests/bpf: add tests for the bpf_numab_ops struct_ops Yafang Shao
2026-10-12 12:13 ` sashiko-bot
2026-10-12 17:51 ` [RFC PATCH v2 0/3] BPF-based per-cgroup NUMA balancing mode selection Tejun Heo
2026-10-13 2:16 ` Yafang Shao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-168093@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=hannes@cmpxchg.org \
--cc=laoar.shao@gmail.com \
--cc=mkoutny@suse.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox