Re: [PATCH v2 0/2] mm: fix PMD level mTHP accounting bugs

From: Nico Pache

Date: Tue Jul 21 2026 - 10:05:30 EST


On Fri, Jul 17, 2026 at 7:29 PM Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> wrote:
>
> On Fri, 17 Jul 2026 00:44:58 -0600 Nico Pache <npache@xxxxxxxxxx> wrote:
>
> > While running selftests I noticed the PMD level per-mTHP stats (nr_anon)
> > remained elevated after each run. After further investigation I noticed
> > this accounting error occurs for both the migration.private_anon_htlb_test
> > and the HMM tests.
> >
> > In the HMM case this is due to folio_add_new_anon_rmap() incrementing the
> > mTHP stats, but never containing a corresponding decrement in
> > free_zone_device_folio(). We solve this by making sure to decrement the
> > counter when freeing device memory.
> >
> > In the migration case, we are incrementing this counter without first
> > checking whether this folio is a hugetlb folio, which relies on a separate
> > accounting system. We solve this by adding the proper hugetlb check before
> > incrementing this counter.
> >
> > With these changes in place, the two tests no longer cause elevated PMD
> > level accounting issues.
>
> Thanks, I've updated mm.git's mm-hotfixes-unstable branch to this
> version.

Thanks!

>
> Sashiko is worried about the existing code ("list corruption or a
> use-after-free panic"):
> https://sashiko.dev/#/patchset/20260717064502.1980173-1-npache@xxxxxxxxxx

https://sashiko.dev/#/patchset/20260717064502.1980173-1-npache@xxxxxxxxxx

I dug into this, although I'm not very familiar with device memory.

It seems we have two options:

a) free_zone_device_folio() unqueue — unqueue zone device folios at
free time, preventing the corruptions/use-after-free.

b) deferred_split_folio() zone-device guard — block at queue time;
covers all callers; stopping the shrinker from ever touching/splitting
a live device folio; makes (a) redundant for this bug, but it could
still be kept as defense.

I added a few people who may be able to help.

Thanks,
-- Nico





>
> >
> > V2 Changes:
> > - add RB from Zi
> > - Drop unnecessary check in __folio_migrate_folio(). HugeTLB has its own
> > migration system in hugetlbfs_migrate_folio().
>
> Here's how v2 altered mm.git:
>
> mm/migrate.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> --- a/mm/migrate.c~b
> +++ a/mm/migrate.c
> @@ -624,8 +624,7 @@ static int __folio_migrate_mapping(struc
> */
> newfolio->index = folio->index;
> newfolio->mapping = folio->mapping;
> - if (folio_test_anon(folio) && folio_test_large(folio) &&
> - !folio_test_hugetlb(folio))
> + if (folio_test_anon(folio) && folio_test_large(folio))
> mod_mthp_stat(folio_order(folio), MTHP_STAT_NR_ANON, 1);
> folio_ref_add(newfolio, nr); /* add cache reference */
> if (folio_test_swapbacked(folio))
> _
>