From nobody Fri Sep 25 21:41:00 2026 Received: from va-1-115.ptr.blmpb.com (va-1-115.ptr.blmpb.com [209.127.230.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77F1C4FECED for ; Tue, 8 Sep 2026 12:25:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.127.230.115 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870347; cv=none; b=J+ksu1c9b9RSUPFsz0BtleYUwfEz7/3lYlPzNiL3OI0hPm9DwPUIpFtl2gaLd2S+/FHafFWjHLsxH5L+Sx6g5K25UkdQqKwZmuq69f4LcE2KJPcDen8/LZxMlRzC/MrYg2zhNBfYWemT0hyQhDA5Xzdaikp3luBjL0dmfqlBRME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870347; c=relaxed/simple; bh=X/fkF1SFtCNVDJowkuYq6PZDajpIxcE8K0KswN79NLs=; h=In-Reply-To:To:Subject:Message-Id:References:Content-Type:Cc: Mime-Version:From:Date; b=ppH+6nBVOlrUOePbn58u7Ie47Po0PB4Ui9y8OBsglMxST0S2NwC4pPQ3f0JQ5vxffnS5NkCvi38u1HZWyWiZswUg8+9EwpxFsN/b6sSWTrME7twpdUj7qrqD25T1bMGoM2gKdLZ5jxPzCCKYBrVWWeqHB3RwGh66efyCOsDkpns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com; spf=pass smtp.mailfrom=bytedance.com; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b=dxc+0Xm9; arc=none smtp.client-ip=209.127.230.115 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bytedance.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b="dxc+0Xm9" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=2212171451; d=bytedance.com; t=1788870341; h=from:subject: mime-version:from:date:message-id:subject:to:cc:reply-to:content-type: mime-version:in-reply-to:message-id; bh=qPzNpzKQioeyUDiUtPms+YsQd8M8xXBqCK2wxk7y+0Q=; b=dxc+0Xm92DCAsFOsZmu3eMCbtdLyzdcl35YtKK9eWwhgzTetFUFCUeFjHP7a4hUtcKl18g aS1FFBIrGM2D5Cw0KsVzfnqmQCz94z3c10w/oo1q616AM44o8Pl2EuFtRY+q4hadPnQ4dK QWpvXxIijU07pV0fAxqHraaMI7IkifB/qddVdPscJRZUxCCDwghuPy3YLo4yTKj87120tA LP/XwttVTlwx+9I06hSxWUGg8Nq16Jz1ggx0mzBI/8VTTFhgcfGEZFLyPYSo00byuJPExc fNPKSJpJu52HAwGUXdHq2Kb/E/KI7TCtEsi5cADNZLz+2sRhh/GN6OseIkNMbw== X-Mailer: git-send-email 2.45.2 X-Lms-Return-Path: In-Reply-To: <20260908122446.56708-1-lizhe.67@bytedance.com> To: , , , , , , , , , Subject: [PATCH 1/4] sched/numa: Track per-process automatic NUMA balancing mode Message-Id: <20260908122446.56708-2-lizhe.67@bytedance.com> References: <20260908122446.56708-1-lizhe.67@bytedance.com> Cc: , , , X-Original-From: Li Zhe Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: "Li Zhe" Date: Tue, 8 Sep 2026 20:24:43 +0800 Content-Type: text/plain; charset="utf-8" Add the internal process mode and scheduler hooks for per-process automatic NUMA balancing control. Any thread in a thread group can change the mode, and the change applies to the whole thread group. Fork inherits the parent process mode, CLONE_THREAD shares it, and exec preserves it. A process mode of enable only allows the process to participate when the global sysctl/static key is enabled and memory policy allows NUMA balancing. Disabling the process mode stops new periodic NUMA scan scheduling and excludes the process from NUMA locality scheduler accounting. Already-installed NUMA hinting PTEs, queued scan work, and other NUMA state are not actively cleared; they drain or age out naturally as the disabled state takes effect. This keeps the slow-path ABI simple and avoids expensive address-space surgery. The configured process mode lives in signal_struct. A separate numa_balancing_sched_enabled field in task_struct is only a scheduler snapshot used by NUMA hot paths and runqueue accounting. It is not part of the userspace-visible process mode. The fork path initializes both pieces of state under current->sighand->siglock before the new task is published. The mode update path serializes concurrent updates, changes the signal mode under siglock, updates the calling task immediately, and then walks the remaining thread list under tasklist_lock to update the rest under sched_change. This keeps rq->nr_numa_running and rq->nr_preferred_running in sync without adding extra hot-path locking. Signed-off-by: Li Zhe --- include/linux/sched.h | 6 +++++ include/linux/sched/numa_balancing.h | 37 ++++++++++++++++++++++++++ include/linux/sched/signal.h | 8 ++++++ init/init_task.c | 4 +++ kernel/fork.c | 8 ++++++ kernel/sched/core.c | 39 ++++++++++++++++++++++++++++ kernel/sched/fair.c | 36 ++++++++++++++++++++++--- 7 files changed, 134 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 8b3d47a325cc..7f1932658d24 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1382,6 +1382,12 @@ struct task_struct { short pref_node_fork; #endif #ifdef CONFIG_NUMA_BALANCING + /* + * Scheduler snapshot of signal_struct::numa_balancing_enabled. It is + * updated with sched_change for runqueue NUMA accounting; the + * user-visible process mode lives in signal_struct. + */ + bool numa_balancing_sched_enabled; int numa_scan_seq; unsigned int numa_scan_period; unsigned int numa_scan_period_max; diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/num= a_balancing.h index 52b22c5c396d..bc413aae5915 100644 --- a/include/linux/sched/numa_balancing.h +++ b/include/linux/sched/numa_balancing.h @@ -8,6 +8,7 @@ */ =20 #include +#include =20 #define TNF_MIGRATED 0x01 #define TNF_NO_GROUP 0x02 @@ -30,6 +31,22 @@ extern void task_numa_fault(int last_node, int node, int= pages, int flags); extern pid_t task_numa_group_id(struct task_struct *p); extern void set_numabalancing_state(bool enabled); extern void task_numa_free(struct task_struct *p, bool final); +static inline bool task_numa_sched_snapshot_enabled(struct task_struct *p) +{ + return READ_ONCE(p->numa_balancing_sched_enabled); +} + +static inline bool task_numa_process_mode_enabled(struct task_struct *p) +{ + return READ_ONCE(p->signal->numa_balancing_enabled); +} + +int task_numa_balancing_set_current(bool enabled); + +static inline int task_numa_balancing_get_current(void) +{ + return task_numa_process_mode_enabled(current); +} bool should_numa_migrate_memory(struct task_struct *p, struct folio *folio, int src_nid, int dst_cpu); #else @@ -47,6 +64,26 @@ static inline void set_numabalancing_state(bool enabled) static inline void task_numa_free(struct task_struct *p, bool final) { } + +static inline bool task_numa_sched_snapshot_enabled(struct task_struct *p) +{ + return false; +} + +static inline bool task_numa_process_mode_enabled(struct task_struct *p) +{ + return false; +} + +static inline int task_numa_balancing_set_current(bool enabled) +{ + return -EINVAL; +} + +static inline int task_numa_balancing_get_current(void) +{ + return -EINVAL; +} static inline bool should_numa_migrate_memory(struct task_struct *p, struct folio *folio, int src_nid, int dst_cpu) { diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 584ae88b435e..fdc03c016cfe 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -179,6 +179,14 @@ struct signal_struct { =20 #ifdef CONFIG_SCHED_AUTOGROUP struct autogroup *autogroup; +#endif +#ifdef CONFIG_NUMA_BALANCING + /* + * Thread-group automatic NUMA balancing mode configured through prctl(). + * Scheduler hot paths use task_struct::numa_balancing_sched_enabled as + * their per-task runqueue accounting snapshot. + */ + bool numa_balancing_enabled; #endif /* * Cumulative resource counters for dead threads in the group, diff --git a/init/init_task.c b/init/init_task.c index adb207cd987c..835bb3f7a17e 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -40,6 +40,9 @@ static struct signal_struct init_signals =3D { .cputimer =3D { .cputime_atomic =3D INIT_CPUTIME_ATOMIC, }, +#endif +#ifdef CONFIG_NUMA_BALANCING + .numa_balancing_enabled =3D true, #endif INIT_CPU_TIMERS(init_signals) .pids =3D { @@ -224,6 +227,7 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = =3D { .vtime.state =3D VTIME_SYS, #endif #ifdef CONFIG_NUMA_BALANCING + .numa_balancing_sched_enabled =3D true, .numa_preferred_nid =3D NUMA_NO_NODE, .numa_group =3D NULL, .numa_faults =3D NULL, diff --git a/kernel/fork.c b/kernel/fork.c index 416758c8a3d4..aff64d75c77f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2496,6 +2496,14 @@ __latent_entropy struct task_struct *copy_process( =20 /* No more failure paths after this point. */ =20 +#ifdef CONFIG_NUMA_BALANCING + p->numa_balancing_sched_enabled =3D + READ_ONCE(current->signal->numa_balancing_enabled); + if (!(clone_flags & CLONE_THREAD)) + p->signal->numa_balancing_enabled =3D + p->numa_balancing_sched_enabled; +#endif + /* * Copy seccomp details explicitly here, in case they were changed * before holding sighand lock. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f78275192036..ba8b22f3ffa5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -603,6 +604,8 @@ int task_llc(const struct task_struct *p) * p->se.load, p->rt_priority, * p->dl.dl_{runtime, deadline, period, flags, bw, density} * - sched_setnuma(): p->numa_preferred_nid + * - task_numa_balancing_set_current(): p->signal->numa_balancing_enabled, + * p->numa_balancing_sched_enabled * - sched_move_task(): p->sched_task_group * - uclamp_update_active() p->uclamp* * @@ -8407,6 +8410,42 @@ void sched_setnuma(struct task_struct *p, int nid) scoped_guard (sched_change, p, DEQUEUE_SAVE) p->numa_preferred_nid =3D nid; } + +static void sched_numa_balancing_change_task(struct task_struct *p, bool e= nabled) +{ + guard(task_rq_lock)(p); + scoped_guard (sched_change, p, DEQUEUE_SAVE) + WRITE_ONCE(p->numa_balancing_sched_enabled, enabled); +} + +int task_numa_balancing_set_current(bool enabled) +{ + static DEFINE_MUTEX(task_numa_balancing_mutex); + struct task_struct *t; + unsigned long flags; + bool old_enabled; + + guard(mutex)(&task_numa_balancing_mutex); + + if (WARN_ON_ONCE(!lock_task_sighand(current, &flags))) + return -ESRCH; + + old_enabled =3D current->signal->numa_balancing_enabled; + if (old_enabled !=3D enabled) + WRITE_ONCE(current->signal->numa_balancing_enabled, enabled); + + unlock_task_sighand(current, &flags); + + if (old_enabled !=3D enabled) { + sched_numa_balancing_change_task(current, enabled); + read_lock(&tasklist_lock); + for_other_threads(current, t) + sched_numa_balancing_change_task(t, enabled); + read_unlock(&tasklist_lock); + } + + return 0; +} #endif /* CONFIG_NUMA_BALANCING */ =20 #ifdef CONFIG_HOTPLUG_CPU diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 8dff37059faf..7dfe275a4bc4 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1712,6 +1713,7 @@ static int get_pref_llc(struct task_struct *p, struct= mm_struct *mm) * conflict only exists for a short period of time. */ if (static_branch_likely(&sched_numa_balancing) && + task_numa_sched_snapshot_enabled(p) && p->numa_preferred_nid >=3D 0 && cpu_to_node(mm_sched_cpu) !=3D p->numa_preferred_nid) mm_sched_llc =3D -1; @@ -1808,6 +1810,9 @@ static void get_scan_cpumasks(cpumask_var_t cpus, str= uct task_struct *p) if (!static_branch_likely(&sched_numa_balancing)) goto out; =20 + if (!task_numa_sched_snapshot_enabled(p)) + goto out; + cpu =3D READ_ONCE(p->mm->sc_stat.cpu); if (cpu !=3D -1) nid =3D cpu_to_node(cpu); @@ -2387,14 +2392,22 @@ static unsigned int task_scan_max(struct task_struc= t *p) =20 static void account_numa_enqueue(struct rq *rq, struct task_struct *p) { - rq->nr_numa_running +=3D (p->numa_preferred_nid !=3D NUMA_NO_NODE); - rq->nr_preferred_running +=3D (p->numa_preferred_nid =3D=3D task_node(p)); + bool enabled =3D task_numa_sched_snapshot_enabled(p); + + rq->nr_numa_running +=3D enabled && + p->numa_preferred_nid !=3D NUMA_NO_NODE; + rq->nr_preferred_running +=3D enabled && + p->numa_preferred_nid =3D=3D task_node(p); } =20 static void account_numa_dequeue(struct rq *rq, struct task_struct *p) { - rq->nr_numa_running -=3D (p->numa_preferred_nid !=3D NUMA_NO_NODE); - rq->nr_preferred_running -=3D (p->numa_preferred_nid =3D=3D task_node(p)); + bool enabled =3D task_numa_sched_snapshot_enabled(p); + + rq->nr_numa_running -=3D enabled && + p->numa_preferred_nid !=3D NUMA_NO_NODE; + rq->nr_preferred_running -=3D enabled && + p->numa_preferred_nid =3D=3D task_node(p); } =20 /* Shared or private faults. */ @@ -3085,6 +3098,9 @@ static bool task_numa_compare(struct task_numa_env *e= nv, goto unlock; } =20 + if (!task_numa_sched_snapshot_enabled(cur)) + goto unlock; + /* Skip this swap candidate if cannot move to the source cpu. */ if (!cpumask_test_cpu(env->src_cpu, cur->cpus_ptr)) goto unlock; @@ -3992,6 +4008,9 @@ void task_numa_fault(int last_cpupid, int mem_node, i= nt pages, int flags) if (!static_branch_likely(&sched_numa_balancing)) return; =20 + if (!task_numa_sched_snapshot_enabled(p)) + return; + /* for example, ksmd faulting in a user's mm */ if (!p->mm) return; @@ -4436,6 +4455,9 @@ static void task_tick_numa(struct rq *rq, struct task= _struct *curr) if (!curr->mm || (curr->flags & (PF_EXITING | PF_KTHREAD)) || work->next = !=3D work) return; =20 + if (!task_numa_sched_snapshot_enabled(curr)) + return; + /* * Using runtime rather than walltime has the dual advantage that * we (mostly) drive the selection from busy threads and that the @@ -4463,6 +4485,9 @@ static void update_scan_period(struct task_struct *p,= int new_cpu) if (!static_branch_likely(&sched_numa_balancing)) return; =20 + if (!task_numa_sched_snapshot_enabled(p)) + return; + if (!p->mm || !p->numa_faults || (p->flags & PF_EXITING)) return; =20 @@ -10475,6 +10500,9 @@ static long migrate_degrades_locality(struct task_s= truct *p, struct lb_env *env) if (!static_branch_likely(&sched_numa_balancing)) return 0; =20 + if (!task_numa_sched_snapshot_enabled(p)) + return 0; + if (!p->numa_faults || !(env->sd->flags & SD_NUMA)) return 0; =20 --=20 2.20.1 From nobody Fri Sep 25 21:41:00 2026 Received: from va-1-111.ptr.blmpb.com (va-1-111.ptr.blmpb.com [209.127.230.111]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B030529410 for ; Tue, 8 Sep 2026 12:26:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.127.230.111 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870407; cv=none; b=pe9NWLxgmum3GwkkwKEoGEXNfm8tqx9kMklpSOeKLRlEAWU/H8ZeLbnwHAFVPPn+p5koJORq8Cq7nXcdLwopnGxoHlu4CsGx1qg/7GkAvSr17bAnkrf6F9ga2G1aNbWCfYlvef+ZfEgqdUi4t3jq7HiXvL5jTJK4U9Biepkox6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870407; c=relaxed/simple; bh=TN7rGqqZ9OR376TXWS3MUze3xcTmiMRRJNOqSnu0G5Q=; h=Content-Type:Cc:Mime-Version:To:From:References:In-Reply-To: Subject:Date:Message-Id; b=eqf1BM1NDwCwyo7+2QJZeesSlSX5YEgdVEhNv8dtu/SUESllZ2Pyn7ahMF2v2zqptU2R8OQpPijoPqrgcfM6SSjmtX5Tp8oesG6+RPRBkjWMNrbW3M+wE6/J7Uj9DFISjjYcz16OfH7oMVms67xNN/dmh1cSWgxaFRTMHzda+ME= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com; spf=pass smtp.mailfrom=bytedance.com; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b=BTzGz8RR; arc=none smtp.client-ip=209.127.230.111 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bytedance.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b="BTzGz8RR" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=2212171451; d=bytedance.com; t=1788870400; h=from:subject: mime-version:from:date:message-id:subject:to:cc:reply-to:content-type: mime-version:in-reply-to:message-id; bh=j33x67pAIPEvtU7LsKxL/lIGzZa4GlqosjlcpBVmf4g=; b=BTzGz8RRpWuVcr8EKWpkSwI3cIr99NYmZ3nn89gU413ahc8ehjOw08V+Ctpei92RK8e5U0 +lCoenJSYb0IUJ+f7NOGcKNzEdWlseqvO/CfFadgb6EsQqwZKZEkmapPgauKmRgvftwHPt o/KsnN2Jelvh5RhE35FaQe9l9x3zNOvY6lIDpP6xtujwzbMjDIljn61dSWjZG9GIZIIriI 9jdlcBfWwPidUOfTnnoFu9/BMgTcFyIIbEiHIh1Mqlg49kKJ7IYO7ylfM08M+AJMCNvwGH BVvFY/vlyg7EQA/XytrVBCh1RrcWPTXa0la9tML9scg29MD2gXaGOhpkYZ9glQ== X-Lms-Return-Path: X-Mailer: git-send-email 2.45.2 Cc: , , , Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 To: , , , , , , , , , From: "Li Zhe" X-Original-From: Li Zhe References: <20260908122446.56708-1-lizhe.67@bytedance.com> In-Reply-To: <20260908122446.56708-1-lizhe.67@bytedance.com> Subject: [PATCH 2/4] sched/numa: Add prctl controls for process mode Date: Tue, 8 Sep 2026 20:24:44 +0800 Message-Id: <20260908122446.56708-3-lizhe.67@bytedance.com> Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Expose the process automatic NUMA balancing mode through prctl(). PR_SET_NUMA_BALANCING accepts PR_NUMA_BALANCING_DISABLE to opt the whole thread group out of future NUMA scanning and PR_NUMA_BALANCING_ENABLE to allow it to participate again when global NUMA balancing and memory policy permit it. PR_GET_NUMA_BALANCING returns the configured process mode, not the effective state after combining the global sysctl/static key and memory policy restrictions. This keeps the ABI weak and predictable: a process can observe and restore the value it configured, while administrators retain kernel.numa_balancing as the top-level hard-off switch. Signed-off-by: Li Zhe --- include/uapi/linux/prctl.h | 6 ++++++ kernel/sys.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index b6ec6f693719..5bc0a2a2a930 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -416,4 +416,10 @@ struct prctl_mm_map { # define PR_CFI_DISABLE _BITUL(1) # define PR_CFI_LOCK _BITUL(2) =20 +/* Per-process automatic NUMA balancing control */ +#define PR_SET_NUMA_BALANCING 82 +#define PR_GET_NUMA_BALANCING 83 +# define PR_NUMA_BALANCING_DISABLE 0 +# define PR_NUMA_BALANCING_ENABLE 1 + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 35b538ba843c..fb01841c0ce9 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -2907,6 +2908,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, a= rg2, unsigned long, arg3, if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE)) error =3D arch_prctl_lock_branch_landing_pad_state(me); break; + case PR_SET_NUMA_BALANCING: + if (arg3 || arg4 || arg5) + return -EINVAL; + if (arg2 !=3D PR_NUMA_BALANCING_DISABLE && + arg2 !=3D PR_NUMA_BALANCING_ENABLE) + return -EINVAL; + error =3D task_numa_balancing_set_current(arg2 =3D=3D + PR_NUMA_BALANCING_ENABLE); + break; + case PR_GET_NUMA_BALANCING: + if (arg2 || arg3 || arg4 || arg5) + return -EINVAL; + error =3D task_numa_balancing_get_current(); + if (error >=3D 0) + error =3D error ? PR_NUMA_BALANCING_ENABLE : + PR_NUMA_BALANCING_DISABLE; + break; default: trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5); error =3D -EINVAL; --=20 2.20.1 From nobody Fri Sep 25 21:41:00 2026 Received: from va-1-114.ptr.blmpb.com (va-1-114.ptr.blmpb.com [209.127.230.114]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 827784D98FB for ; Tue, 8 Sep 2026 12:27:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.127.230.114 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870426; cv=none; b=CZDXCMdK2UiNpWXcQIAkoGcops5JnWiKXrAmZVzFhe7yeEzPijeM05k3q0Tfq6KKZTfqgtpgqqQrU4aPBMD/JfZPH72us7659h2f4F4WMPfeiC4EkYTp5JBPHshK1V54jdeGCcSFmzaODSodTdXikB6XbeaExw6pay8ahQhEFIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870426; c=relaxed/simple; bh=I29Os0R0hyQ1NQTq5qpo5BNWrAZgpzaiFVdaMzzBGbQ=; h=Cc:Message-Id:To:From:References:Content-Type:Subject:Date: Mime-Version:In-Reply-To; b=L0+/fLty8q+fezd9UgxFtj3tJVtzVe0b21ndh/JShEmPI4AZSTYdXycNCxMZT6wQhtWJNVixUrWrxI+1SCTPVnlZ63FA4RSUVexRmRHT9Mjho87LE8ToSSRNconPK+jjfQj5JhR7jCItZa/FaqcHWArtfQ2CCcjpCTxkoZq8xKU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com; spf=pass smtp.mailfrom=bytedance.com; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b=J3hcc8Bm; arc=none smtp.client-ip=209.127.230.114 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bytedance.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b="J3hcc8Bm" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=2212171451; d=bytedance.com; t=1788870419; h=from:subject: mime-version:from:date:message-id:subject:to:cc:reply-to:content-type: mime-version:in-reply-to:message-id; bh=jriAg666w9csUkbR5t2/Iux9iPMbescST4uj3QwAtRs=; b=J3hcc8BmK5S6Y4seMrz2INpE/yVxPA+sOjwKqZEdtHOvDvLB/Lp09uVrJ2Cu/PLXJSyhCv HU9SHP0rvKbwcWx7Nu5aF4346z5HKCBFSGXkIm/1WxxpzR6hgTfl+IE16r02ci8oR3MuHx HCb9pY4LGnnG9I8jNe/Kgx3IaYKTmIxQQBaBThu9bUrawshlp0Xn8cUkFz+jGT6lVR4mFM kPOkBszsQoYlMIE+UheWboEUFnuggDBAmdmu4rxF712/VY1OkKkDxBtaMPJIW1KZyuEU0y 8nyyNluRPndUcaCZT0PJCcD6TOQLyCy1PMkmmozRVJiixW8GA151utI7ZffJaw== Cc: , , , Message-Id: <20260908122446.56708-4-lizhe.67@bytedance.com> X-Mailer: git-send-email 2.45.2 To: , , , , , , , , , From: "Li Zhe" References: <20260908122446.56708-1-lizhe.67@bytedance.com> X-Lms-Return-Path: Content-Transfer-Encoding: quoted-printable Subject: [PATCH 3/4] proc: Report process NUMA balancing mode Date: Tue, 8 Sep 2026 20:24:45 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 In-Reply-To: <20260908122446.56708-1-lizhe.67@bytedance.com> X-Original-From: Li Zhe Content-Type: text/plain; charset="utf-8" Add NumaB_mode to /proc//status so users can inspect the configured process automatic NUMA balancing mode without issuing a prctl() from the target process. The field reports the process mode as enabled or disabled when automatic NUMA balancing is supported, and unsupported when the kernel is built without CONFIG_NUMA_BALANCING. Effective behavior still depends on the global numa_balancing sysctl and memory policy. Signed-off-by: Li Zhe --- fs/proc/array.c | 16 ++++++++++++++++ include/linux/sched/numa_balancing.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/fs/proc/array.c b/fs/proc/array.c index f6f75d206762..a27a6a57e8b2 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -425,6 +425,21 @@ static inline void task_thp_status(struct seq_file *m,= struct mm_struct *mm) seq_printf(m, "THP_enabled:\t%d\n", thp_enabled); } =20 +#ifdef CONFIG_NUMA_BALANCING +static inline void task_numa_balancing_status(struct seq_file *m, + struct task_struct *task) +{ + seq_printf(m, "NumaB_mode:\t%s\n", + task_numa_balancing_mode_name(task)); +} +#else +static inline void task_numa_balancing_status(struct seq_file *m, + struct task_struct *task) +{ + seq_puts(m, "NumaB_mode:\tunsupported\n"); +} +#endif + static inline void task_untag_mask(struct seq_file *m, struct mm_struct *m= m) { seq_printf(m, "untag_mask:\t%#lx\n", mm_untag_mask(mm)); @@ -453,6 +468,7 @@ int proc_pid_status(struct seq_file *m, struct pid_name= space *ns, task_untag_mask(m, mm); mmput(mm); } + task_numa_balancing_status(m, task); task_sig(m, task); task_cap(m, task); task_seccomp(m, task); diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/num= a_balancing.h index bc413aae5915..69e79359fa22 100644 --- a/include/linux/sched/numa_balancing.h +++ b/include/linux/sched/numa_balancing.h @@ -47,6 +47,11 @@ static inline int task_numa_balancing_get_current(void) { return task_numa_process_mode_enabled(current); } + +static inline const char *task_numa_balancing_mode_name(struct task_struct= *p) +{ + return task_numa_process_mode_enabled(p) ? "enabled" : "disabled"; +} bool should_numa_migrate_memory(struct task_struct *p, struct folio *folio, int src_nid, int dst_cpu); #else --=20 2.20.1 From nobody Fri Sep 25 21:41:00 2026 Received: from sg-3-111.ptr.tlmpb.com (sg-3-111.ptr.tlmpb.com [101.45.255.111]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28EFB3D6CDD for ; Tue, 8 Sep 2026 12:28:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=101.45.255.111 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870499; cv=none; b=ZkqA2Nd1jyMv2rYF27H+2AkK0chaGoYyK8GCVqVYGGjAGMMxeCNCCUKByACbZTOJGsuyK80D+DU/VArdwR/fPF/gWdvHfzQeCxXxEnMSfYpseUBShGRQB/UPTBpeXvOdYZMhgEjU9XSQct6MuNUlzKoO3nMSZ79He+/b9c8dFTM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788870499; c=relaxed/simple; bh=CAWNFS566Mb/PBl/Fdw1exjQuJBSVd6ATh2wTNizWAs=; h=To:Date:Mime-Version:References:From:In-Reply-To:Content-Type:Cc: Subject:Message-Id; b=WmkjPy/OWRSjor2aZwdNGRU2SQqqdSBg57DqhKwU5n97Mb6Nt6HvYmqLv1/C2anxSs70Tyze2Rrz9KwUdg4a8TyYSfjHMNd2F4+wPMScj7ptGFYlhd0ndsdSEbDIaXtCwcowumnJSpRMXD22D7ale/r3smPR8KMLgvlNQRDOiYw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com; spf=pass smtp.mailfrom=bytedance.com; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b=KMSJRMcv; arc=none smtp.client-ip=101.45.255.111 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bytedance.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b="KMSJRMcv" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=2212171451; d=bytedance.com; t=1788870448; h=from:subject: mime-version:from:date:message-id:subject:to:cc:reply-to:content-type: mime-version:in-reply-to:message-id; bh=oU1SN1evCfMvWApaJ8Az3rYN4gJaNSTnoUYsE3H6ZNc=; b=KMSJRMcvibOHpw8yDZ/5L3eGliGjEvwsRLTvMG1iHf0zZOuoP5fLgWAKpBY6lfOMOsqk1o 077FfQ0obyIDZ/tdPbKrSlIUfrkvUPdnmtFLiP0q9k790PmQWInmdwlmlf3mCXDYWWpJJP LL1GaXUzUJWTi+OlkH4CwPz/PHM6NlEFmF2s4m9M1lqZazeCZuWA2xeGf/vRc2TVwLePE+ WVqQVGHSIOeP1vUF5kT/OzBfsU3KadMipgUOuBRBx3/xFnEYXTtKd2EIrhK+YBMDb0qZL3 blcbRk+GRYYJY5ReT/MfD/aXQbSOSc0r+UpoVy3MgljgbQOdwYCVsnEMGnbo+A== To: , , , , , , , , , Date: Tue, 8 Sep 2026 20:24:46 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260908122446.56708-1-lizhe.67@bytedance.com> From: "Li Zhe" Content-Transfer-Encoding: quoted-printable In-Reply-To: <20260908122446.56708-1-lizhe.67@bytedance.com> Cc: , , , Subject: [PATCH 4/4] Documentation: Describe per-process NUMA balancing control Message-Id: <20260908122446.56708-5-lizhe.67@bytedance.com> X-Mailer: git-send-email 2.45.2 X-Original-From: Li Zhe X-Lms-Return-Path: Content-Type: text/plain; charset="utf-8" Document the PR_SET_NUMA_BALANCING and PR_GET_NUMA_BALANCING operations near the kernel.numa_balancing sysctl documentation, and describe the NumaB_mode field in /proc//status. Signed-off-by: Li Zhe --- Documentation/admin-guide/sysctl/kernel.rst | 16 ++++++++++++++++ Documentation/filesystems/proc.rst | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/ad= min-guide/sysctl/kernel.rst index b6328cd0f43e..7f665c28828a 100644 --- a/Documentation/admin-guide/sysctl/kernel.rst +++ b/Documentation/admin-guide/sysctl/kernel.rst @@ -754,6 +754,22 @@ different types of memory (represented as different NU= MA nodes) to place the hot pages in the fast memory. This is implemented based on unmapping and page fault too. =20 +The ``PR_SET_NUMA_BALANCING`` and ``PR_GET_NUMA_BALANCING`` prctl(2) +operations can be used by a process to opt out of automatic NUMA balancing +or re-enable participation for the whole thread group. Any thread in the +thread group may change the process setting. The setting is inherited by +fork(2), is shared by threads created with clone(2) ``CLONE_THREAD`` and is +preserved across execve(2). The global ``numa_balancing`` sysctl remains +the top-level control: a process-level enable does not turn automatic NUMA +balancing on when it is disabled system-wide. Memory policy still applies, +so the process setting does not make VMAs participate when their policy +prevents automatic NUMA balancing. + +Disabling the process setting stops scheduling new periodic NUMA scans for +that process. Existing NUMA hinting PTEs and already queued work are not +actively cleared and may still drain naturally as the disabled state takes +effect. + numa_balancing_promote_rate_limit_MBps =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems= /proc.rst index c102b62023cd..a4e9037a3161 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -188,6 +188,7 @@ read the file /proc/PID/status:: HugetlbPages: 0 kB CoreDumping: 0 THP_enabled: 1 + NumaB_mode: enabled Threads: 1 SigQ: 0/28578 SigPnd: 0000000000000000 @@ -274,6 +275,11 @@ It's slow but very precise. THP_enabled process is allowed to use THP (returns 0 when PR_SET_THP_DISABLE is set on the process to d= isable THP completely, not just partially) + NumaB_mode process automatic NUMA balancing mode: + enabled or disabled when supported, otherwise + unsupported; the effective behavior also depe= nds + on the global numa_balancing sysctl and memory + policy Threads number of threads SigQ number of signals queued/max. number for queue SigPnd bitmap of pending signals for the thread --=20 2.20.1