Re: [RFC PATCH] mm/huge_memory: do not add dropped split tail folios to LRU
From: Matthew Wilcox
Date: Thu Jun 11 2026 - 23:45:20 EST
On Thu, Jun 11, 2026 at 03:45:19PM +0800, Zhaoyang Huang wrote:
> > > pin_user_pages*(..., FOLL_LONGTERM)
> > > └─ __gup_longterm_locked() [gup.c:2465]
> > > │ ├─ follow_page_pte() [gup.c:802]
> > > │ │ └─ try_grab_folio() [gup.c:858]
> > > if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
> > > return -ENOMEM;
> > >
> > > // Could __folio_split->folio_put could
> > > race here ?
> > > if (flags & FOLL_GET)
> > > folio_ref_add(folio, refs);
> > > └─ check_and_migrate_movable_pages() [gup.c:2490]
> > > └─ collect_longterm_unpinnable_folios() [gup.c:2391]
> > > └─ └─if (!folio_isolate_lru(folio))
> > >
> > > Could the __folio_split race in the above scenario? It looks like
> > > try_grab_folio set the refcount without using atomic operation.
> >
> > folio_ref_add() used by try_grab_folio() is an atomic op.
> > Which refcount change is not atomic here?
> The atomic I mean is folio_try_get is implemented by
> atomic_add_unless, while try_grab_folio does this by the below
> sequence which leaves a window to have __folio_split race with it.
> right?
>
> if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
> ....
>
> if (flags & FOLL_GET)
> folio_ref_add(folio, refs);
No. try_grab_folio() is only called when we already have a reference to
the folio. It says so right in the comment:
* It is called when we have a stable reference for the folio, typically in
* GUP slow path.
You may not be able to see it; in the GUP slow path, we have a lock
preventing unmapping, and the folio is mapped, therefore
there's a reference count on the folio already. This isn't true for
try_grab_folio_fast(), which is why it uses try_get instead of ref_add.