Re:Re: [PATCH] mm/damon/ops-common: putback folios on invalid migrate nid
李佑鸿 <[email protected]> Fri, 24 Jul 2026 14:00:30 +0800 (CST)
| Newsgroups | dev.linux.lists.damon |
|---|---|
| Message-ID | <[email protected]> |
Thanks for the review. At 2026-07-23 21:46:22, "SJ Park" <[email protected]> wrote: >On Thu, 23 Jul 2026 14:12:46 +0800 [email protected] wrote: > >> From: liyouhong <[email protected]> >> >> damon_pa_migrate() and damos_va_migrate() isolate folios into a local list >> and then call damon_migrate_pages(). When target_nid is invalid (including >> the scheme default NUMA_NO_NODE / -1), damon_migrate_pages() returns early >> without putting the folios back to the LRU. >> >> Callers then discard the list head while those folios remain isolated with >> an extra reference taken by folio_isolate_lru(). The pages stay off the >> LRU for as long as the mapping exists (anon active+inactive counts drop >> while RSS does not), and the leftover references can pin the pages after >> the mapping is gone. > >Nice catch! > >Sounds like this is a very bad bug. Users can trigger it (though it is >arguably weird or poor setup at least) and the consequence is quote bad: >visible but silent memory exhaustion that cannot be restored without reboot. I >believe this deserves the hot fixes fast track. Let me know if I'm missing >something. > Users can hit it by creating a migrate_{hot,cold} scheme without changing target_nid (the sysfs default is NUMA_NO_NODE / -1), or by pointing it at a non-memory node. Each apply cycle isolates folios, then damon_migrate_pages() returns without putback and the callers discard the list heads. The pages leave the LRU while the process RSS stays up; after the mapping is gone, the leftover isolate refs keep them pinned until reboot. I do not think you are missing anything. >> >> Factor the existing putback loop into damon_putback_folio_list() and use it >> on the invalid-nid path as well, so ignored migration requests still return >> folios to the LRU. > >As this is a hotfix, I'd prefer skipping putback loop facotring out part, for >simplicity of backporting. > >> >> Fixes: 7e6c3130690a ("mm/damon/ops-common: ignore migration request to invalid nodes") > >Let's Cc: stable@. > >> Signed-off-by: liyouhong <[email protected]> >> --- >> mm/damon/ops-common.c | 22 +++++++++++++++------- >> 1 file changed, 15 insertions(+), 7 deletions(-) >> >> diff --git a/mm/damon/ops-common.c b/mm/damon/ops-common.c >> index d1842e2b00ef..9a1e8aec5444 100644 >> --- a/mm/damon/ops-common.c >> +++ b/mm/damon/ops-common.c >> @@ -331,12 +331,22 @@ static unsigned int __damon_migrate_folio_list( >> return nr_succeeded; >> } >> >> +static void damon_putback_folio_list(struct list_head *folio_list) >> +{ >> + struct folio *folio; >> + >> + while (!list_empty(folio_list)) { >> + folio = lru_to_folio(folio_list); >> + list_del(&folio->lru); >> + folio_putback_lru(folio); >> + } >> +} >> + >> static unsigned int damon_migrate_folio_list(struct list_head *folio_list, >> struct pglist_data *pgdat, >> int target_nid) >> { >> unsigned int nr_migrated = 0; >> - struct folio *folio; >> LIST_HEAD(ret_folios); >> LIST_HEAD(migrate_folios); >> >> @@ -374,11 +384,7 @@ static unsigned int damon_migrate_folio_list(struct list_head *folio_list, >> >> list_splice(&ret_folios, folio_list); >> >> - while (!list_empty(folio_list)) { >> - folio = lru_to_folio(folio_list); >> - list_del(&folio->lru); >> - folio_putback_lru(folio); >> - } >> + damon_putback_folio_list(folio_list); > >I agree this is good cleanup. For simple porting to stable@ series, however, >let's not touch this function. > >> >> return nr_migrated; >> } >> @@ -394,8 +400,10 @@ unsigned long damon_migrate_pages(struct list_head *folio_list, int target_nid) >> return nr_migrated; >> >> if (target_nid < 0 || target_nid >= MAX_NUMNODES || >> - !node_state(target_nid, N_MEMORY)) >> + !node_state(target_nid, N_MEMORY)) { > >Please keep the original indentation. > >> + damon_putback_folio_list(folio_list); >> return nr_migrated; >> + } > >Let's open-code the putback here. We could factor out that later. v2 follows your suggestions: drop the putback helper so the change is easier to backport, open-code the putback only on the invalid-nid path, keep the original indentation, and Cc stable@. Best regards, liyouhong