Re: [RFC PATCH 2/4] mm: kpromoted: Hot page info collection and promotion daemon

Davidlohr Bueso
2025-03-13T16:44:43Z

On Thu, 06 Mar 2025, Bharata B Rao wrote:

>+static int page_should_be_promoted(struct page_hotness_info *phi)
>+{
>+ struct page *page = pfn_to_online_page(phi->pfn);
>+ unsigned long now = jiffies;
>+ struct folio *folio;
>+
>+ if (!page || is_zone_device_page(page))
>+ return false;
>+
>+ folio = page_folio(page);
>+ if (!folio_test_lru(folio)) {
>+ count_vm_event(KPROMOTED_MIG_NON_LRU);
>+ return false;
>+ }
>+ if (folio_nid(folio) == phi->hot_node) {
>+ count_vm_event(KPROMOTED_MIG_RIGHT_NODE);
>+ return false;
>+ }

How about using the LRU age itself:

if (folio_test_active())
return true;

>+
>+ /* If the page was hot a while ago, don't promote */
>+ if ((now - phi->last_update) > 2 * msecs_to_jiffies(KPROMOTED_FREQ_WINDOW)) {
>+ count_vm_event(KPROMOTED_MIG_COLD_OLD);
>+ return false;
>+ }
>+
>+ /* If the page hasn't been accessed enough number of times, don't promote */
>+ if (phi->frequency < KPRMOTED_FREQ_THRESHOLD) {
>+ count_vm_event(KPROMOTED_MIG_COLD_NOT_ACCESSED);
>+ return false;
>+ }
>+ return true;
>+}

...

>+static int kpromoted(void *p)
>+{
>+ pg_data_t *pgdat = (pg_data_t *)p;
>+ struct task_struct *tsk = current;
>+ long timeout = msecs_to_jiffies(KPROMOTE_DELAY);
>+
>+ const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
>+
>+ if (!cpumask_empty(cpumask))
>+ set_cpus_allowed_ptr(tsk, cpumask);

Explicit cpumasks are not needed if you use kthread_create_on_node().

See https://web.git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=c6a566f6c1b4d5dff659acd221f95a72923f4085

>+
>+ while (!kthread_should_stop()) {
>+ wait_event_timeout(pgdat->kpromoted_wait,
>+ kpromoted_work_requested(pgdat), timeout);
>+ kpromoted_do_work(pgdat);
>+ }
>+ return 0;
>+}
>+
>+static void kpromoted_run(int nid)
>+{
>+ pg_data_t *pgdat = NODE_DATA(nid);
>+
>+ if (pgdat->kpromoted)
>+ return;
>+
>+ pgdat->kpromoted = kthread_run(kpromoted, pgdat, "kpromoted%d", nid);
>+ if (IS_ERR(pgdat->kpromoted)) {
>+ pr_err("Failed to start kpromoted on node %d\n", nid);
>+ pgdat->kpromoted = NULL;
>+ }
>+}
>+