Re: [PATCH v3 5/7] sched/numa: scan PID-inactive VMAs for promotion

From: David Hildenbrand (Arm)

Date: Fri Sep 25 2026 - 06:55:50 EST


On 9/22/26 20:29, Gregory Price wrote:
> From: "Gregory Price (Meta)" <gourry@xxxxxxxxxx>
>
> Commit fc137c0ddab2 ("sched/numa: enhance vma scanning logic") skips
> VMAs without recent PID activity. Since only NUMA hint faults record
> that activity, the filter can suppress the fault needed to promote hot
> slow-tier memory.
>
> Let memory tiering bypass the PID scan filter. In combined mode, use the
> placement decision to restrict top-tier sampling to VMAs that need it,
> while inactive VMAs still receive promotion-only scans.
>
> Track the last completed placement scan separately from scans of any
> kind. Promotion-only scans still update prev_scan_seq, but do not
> advance the placement-starvation horizon.
>
> On a host with 768 GB of DRAM and 256 GB of CXL memory, one large shmem
> VMA consumed most scanning activity, while 2,537 other VMAs covering
> 84 GB were skipped as inactive. One stand-out result: a hot 20 GB hash
> table ended up trapped entirely on CXL and drove CXL bandwidth
> utilization beyond sustainable levels - resulting in a large regression.
>
> With this series, the hot hash table ends up split evenly between DRAM
> and CXL, tier residency tracked runtime load, and CXL bandwidth
> utilization drops from 45GB/s (maxed) to 5-10GB/s, while DRAM bandwidth
> utilization increases from ~200GB/s to 250GB/s+, resulting in major
> throughput improvements for the database workload.
>
> Fixes: fc137c0ddab2 ("sched/numa: enhance vma scanning logic")
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: OpenAI:gpt-5
> Signed-off-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
> ---
> include/linux/mm_types.h | 7 +++++++
> kernel/sched/fair.c | 26 +++++++++++++++++++++-----
> 2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index fd35db969bc94..dcca3ead9db59 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -804,6 +804,13 @@ struct vma_numab_state {
> */
> int prev_scan_seq;
>
> + /*
> + * MM scan sequence ID when the VMA was last scanned for placement.
> + * The starvation horizon in vma_needs_placement_scan() counts against
> + * this, so promotion-only scans cannot postpone placement indefinitely.
> + */
> + int prev_placement_scan_seq;
> +
> /* Preserve placement-scan eligibility during an in-progress scan. */
> bool placement_scan;
> };
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index a2849e72c4e26..412c72084a63d 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -4097,7 +4097,7 @@ static bool vma_needs_placement_scan(struct mm_struct *mm,
> * threads can help scan this vma, force a vma scan.
> */
> if (READ_ONCE(mm->numa_scan_seq) >
> - (vma->numab_state->prev_scan_seq + get_nr_threads(current)))
> + (vma->numab_state->prev_placement_scan_seq + get_nr_threads(current)))
> return true;
>
> return false;
> @@ -4267,7 +4267,8 @@ static void task_numa_work(struct callback_head *work)
> * to prevent VMAs being skipped prematurely on the
> * first scan:
> */
> - vma->numab_state->prev_scan_seq = mm->numa_scan_seq - 1;
> + vma->numab_state->prev_scan_seq = mm->numa_scan_seq - 1;
> + vma->numab_state->prev_placement_scan_seq = mm->numa_scan_seq - 1;
> }
>
> /*
> @@ -4300,10 +4301,13 @@ static void task_numa_work(struct callback_head *work)
> * Do not scan the VMA if a task has not accessed it, unless no other
> * VMA candidate exists. If a scan is already in-progress, finish it,
> * but track continuation separately from starting a new one.
> + *
> + * The PID filter must not gate promotion. Allow PID-inactive VMAs
> + * to proceed when memory tiering is enabled.
> */
> placement_due = vma_needs_placement_scan(mm, vma);
> scan_started = mm->numa_scan_offset > vma->vm_start;
> - pid_scan_allowed = vma_pids_forced || placement_due;
> + pid_scan_allowed = tiering || vma_pids_forced || placement_due;
>
> if (!pid_scan_allowed) {
> if (scan_started) {
> @@ -4315,10 +4319,16 @@ static void task_numa_work(struct callback_head *work)
> }
> }
>
> - /* Keep scan policy stable while processing a VMA in chunks.*/
> + /*
> + * Keep scan policy stable while processing a VMA in chunks.
> + * A fault in one chunk can make a VMA placement-eligible. Keep a
> + * promotion-only decision sticky for the rest of a partial scan.
> + */
> placement_scan &= numab_mode & NUMA_BALANCING_NORMAL;
> if (scan_started)
> placement_scan &= vma->numab_state->placement_scan;
> + else if (tiering)
> + placement_scan &= placement_due;

Same comment. Apart from that LGTM.

--
Cheers,

David