mm: Create/affine kcompactd to its preferred node

JIRA: https://issues.redhat.com/browse/RHEL-135521
Conflicts:
  * minor contextual difference in the 1st hunk due to out-of-order
    backport of upstream commit  ce6d9c1c2b5c ("NFS: fix nfs_release_folio()
    to not deadlock via kcompactd writeback")

commit 54880b5a2b5ea6d32dd970125b9b1b033b86ae93
Author: Frederic Weisbecker <frederic@kernel.org>
Date:   Fri Sep 27 00:49:02 2024 +0200

    mm: Create/affine kcompactd to its preferred node

    Kcompactd is dedicated to a specific node. As such it wants to be
    preferrably affine to it, memory and CPUs-wise.

    Use the proper kthread API to achieve that. As a bonus it takes care of
    CPU-hotplug events and CPU-isolation on its behalf.

    Acked-by: Vlastimil Babka <vbabka@suse.cz>
    Acked-by: Michal Hocko <mhocko@suse.com>
    Signed-off-by: Frederic Weisbecker <frederic@kernel.org>

Signed-off-by: Rafael Aquini <raquini@redhat.com>
This commit is contained in:
Rafael Aquini
2026-01-20 11:14:06 -05:00
parent caac40a2b4
commit c670acc5c4
+3 -40
View File
@@ -3074,15 +3074,9 @@ void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx)
static int kcompactd(void *p)
{
pg_data_t *pgdat = (pg_data_t *)p;
struct task_struct *tsk = current;
long default_timeout = msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC);
long timeout = default_timeout;
const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
if (!cpumask_empty(cpumask))
set_cpus_allowed_ptr(tsk, cpumask);
current->flags |= PF_KCOMPACTD;
set_freezable();
@@ -3156,10 +3150,12 @@ void __meminit kcompactd_run(int nid)
if (pgdat->kcompactd)
return;
pgdat->kcompactd = kthread_run(kcompactd, pgdat, "kcompactd%d", nid);
pgdat->kcompactd = kthread_create_on_node(kcompactd, pgdat, nid, "kcompactd%d", nid);
if (IS_ERR(pgdat->kcompactd)) {
pr_err("Failed to start kcompactd on node %d\n", nid);
pgdat->kcompactd = NULL;
} else {
wake_up_process(pgdat->kcompactd);
}
}
@@ -3177,30 +3173,6 @@ void __meminit kcompactd_stop(int nid)
}
}
/*
* It's optimal to keep kcompactd on the same CPUs as their memory, but
* not required for correctness. So if the last cpu in a node goes
* away, we get changed to run anywhere: as the first one comes back,
* restore their cpu bindings.
*/
static int kcompactd_cpu_online(unsigned int cpu)
{
int nid;
for_each_node_state(nid, N_MEMORY) {
pg_data_t *pgdat = NODE_DATA(nid);
const struct cpumask *mask;
mask = cpumask_of_node(pgdat->node_id);
if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
/* One of our CPUs online: restore mask */
if (pgdat->kcompactd)
set_cpus_allowed_ptr(pgdat->kcompactd, mask);
}
return 0;
}
static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
int write, void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -3261,15 +3233,6 @@ static struct ctl_table vm_compaction[] = {
static int __init kcompactd_init(void)
{
int nid;
int ret;
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"mm/compaction:online",
kcompactd_cpu_online, NULL);
if (ret < 0) {
pr_err("kcompactd: failed to register hotplug callbacks.\n");
return ret;
}
for_each_node_state(nid, N_MEMORY)
kcompactd_run(nid);