* [PATCH] mm/huge_memory: Initialise workingset state before folio split
@ 2026-07-24 19:52 Matt Fleming
2026-07-24 20:18 ` Zi Yan
0 siblings, 1 reply; 4+ messages in thread
From: Matt Fleming @ 2026-07-24 19:52 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Dave Chinner, Qi Zheng, Roman Gushchin, Muchun Song,
Kairui Song, Shakeel Butt, Matthew Wilcox,
syzbot+c5b060ce82921a2fd500, stable, linux-mm, linux-kernel,
kernel-team, Matt Fleming
From: Matt Fleming <mfleming@cloudflare.com>
xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but
__folio_split() leaves the xa_state's xa_lru unset. That lets a live,
memcg-charged xa_node exist without being linked into the mapping's
shadow_nodes list_lru; when reclaim later walks the list_lru it trips
VM_WARN_ON(!css_is_dying()).
Use mapping_set_update() to install both the workingset update callback
and the shadow_nodes list_lru on the xa_state.
Reported-by: syzbot+c5b060ce82921a2fd500@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c5b060ce82921a2fd500
Fixes: 58729c04cf10 ("mm/huge_memory: add buddy allocator like (non-uniform) folio_split()")
Cc: stable@vger.kernel.org
Signed-off-by: Matt Fleming <mfleming@cloudflare.com>
---
mm/huge_memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index b5d1e9d4463d..12d0e0b14e83 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4033,7 +4033,8 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
gfp_t gfp;
mapping = folio->mapping;
- min_order = mapping_min_folio_order(folio->mapping);
+ mapping_set_update(&xas, mapping);
+ min_order = mapping_min_folio_order(mapping);
if (new_order < min_order) {
ret = -EINVAL;
goto out;
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] mm/huge_memory: Initialise workingset state before folio split 2026-07-24 19:52 [PATCH] mm/huge_memory: Initialise workingset state before folio split Matt Fleming @ 2026-07-24 20:18 ` Zi Yan 2026-07-24 20:26 ` Zi Yan 0 siblings, 1 reply; 4+ messages in thread From: Zi Yan @ 2026-07-24 20:18 UTC (permalink / raw) To: Matt Fleming Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Dave Chinner, Qi Zheng, Roman Gushchin, Muchun Song, Kairui Song, Shakeel Butt, Matthew Wilcox, syzbot+c5b060ce82921a2fd500, stable, linux-mm, linux-kernel, kernel-team, Matt Fleming On 24 Jul 2026, at 15:52, Matt Fleming wrote: > From: Matt Fleming <mfleming@cloudflare.com> > > xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but > __folio_split() leaves the xa_state's xa_lru unset. That lets a live, But mapping_set_update() is not required for xas_split_alloc() and xas_split(), or at least nothing triggered for uniform split path. Why? xas_split_alloc() uses gfp = current_gfp_context(mapping_gfp_mask(mapping) & GFP_RECLAIM_MASK), whereas xas_try_split() starts with GFP_NOWAIT and follows xas_nomem() by adding __GFP_ACCOUNT if XA_FLAGS_ACCOUNT is set. Should xas_split_alloc() also take a gfp input and the caller gets gfp the same way as xas_split_alloc()? > memcg-charged xa_node exist without being linked into the mapping's > shadow_nodes list_lru; when reclaim later walks the list_lru it trips > VM_WARN_ON(!css_is_dying()). > > Use mapping_set_update() to install both the workingset update callback > and the shadow_nodes list_lru on the xa_state. > > Reported-by: syzbot+c5b060ce82921a2fd500@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=c5b060ce82921a2fd500 > Fixes: 58729c04cf10 ("mm/huge_memory: add buddy allocator like (non-uniform) folio_split()") > Cc: stable@vger.kernel.org > Signed-off-by: Matt Fleming <mfleming@cloudflare.com> > --- > mm/huge_memory.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > index b5d1e9d4463d..12d0e0b14e83 100644 > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -4033,7 +4033,8 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > gfp_t gfp; > > mapping = folio->mapping; > - min_order = mapping_min_folio_order(folio->mapping); > + mapping_set_update(&xas, mapping); > + min_order = mapping_min_folio_order(mapping); > if (new_order < min_order) { > ret = -EINVAL; > goto out; > -- > 2.43.0 Best Regards, Yan, Zi ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/huge_memory: Initialise workingset state before folio split 2026-07-24 20:18 ` Zi Yan @ 2026-07-24 20:26 ` Zi Yan 2026-07-25 3:16 ` Zi Yan 0 siblings, 1 reply; 4+ messages in thread From: Zi Yan @ 2026-07-24 20:26 UTC (permalink / raw) To: Matt Fleming Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Dave Chinner, Qi Zheng, Roman Gushchin, Muchun Song, Kairui Song, Shakeel Butt, Matthew Wilcox, syzbot+c5b060ce82921a2fd500, stable, linux-mm, linux-kernel, kernel-team, Matt Fleming Use Lorenzo’s current email. On 24 Jul 2026, at 16:18, Zi Yan wrote: > On 24 Jul 2026, at 15:52, Matt Fleming wrote: > >> From: Matt Fleming <mfleming@cloudflare.com> >> >> xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but >> __folio_split() leaves the xa_state's xa_lru unset. That lets a live, > > But mapping_set_update() is not required for xas_split_alloc() and xas_split(), > or at least nothing triggered for uniform split path. Why? > > xas_split_alloc() uses > gfp = current_gfp_context(mapping_gfp_mask(mapping) & GFP_RECLAIM_MASK), > whereas xas_try_split() starts with GFP_NOWAIT and follows xas_nomem() > by adding __GFP_ACCOUNT if XA_FLAGS_ACCOUNT is set. > > Should xas_split_alloc() also take a gfp input and the caller gets > gfp the same way as xas_split_alloc()? > >> memcg-charged xa_node exist without being linked into the mapping's >> shadow_nodes list_lru; when reclaim later walks the list_lru it trips >> VM_WARN_ON(!css_is_dying()). >> >> Use mapping_set_update() to install both the workingset update callback >> and the shadow_nodes list_lru on the xa_state. >> >> Reported-by: syzbot+c5b060ce82921a2fd500@syzkaller.appspotmail.com >> Closes: https://syzkaller.appspot.com/bug?extid=c5b060ce82921a2fd500 >> Fixes: 58729c04cf10 ("mm/huge_memory: add buddy allocator like (non-uniform) folio_split()") >> Cc: stable@vger.kernel.org >> Signed-off-by: Matt Fleming <mfleming@cloudflare.com> >> --- >> mm/huge_memory.c | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >> index b5d1e9d4463d..12d0e0b14e83 100644 >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -4033,7 +4033,8 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >> gfp_t gfp; >> >> mapping = folio->mapping; >> - min_order = mapping_min_folio_order(folio->mapping); >> + mapping_set_update(&xas, mapping); >> + min_order = mapping_min_folio_order(mapping); >> if (new_order < min_order) { >> ret = -EINVAL; >> goto out; >> -- >> 2.43.0 > > > Best Regards, > Yan, Zi Best Regards, Yan, Zi ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/huge_memory: Initialise workingset state before folio split 2026-07-24 20:26 ` Zi Yan @ 2026-07-25 3:16 ` Zi Yan 0 siblings, 0 replies; 4+ messages in thread From: Zi Yan @ 2026-07-25 3:16 UTC (permalink / raw) To: Matt Fleming Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Dave Chinner, Qi Zheng, Roman Gushchin, Muchun Song, Kairui Song, Shakeel Butt, Matthew Wilcox, syzbot+c5b060ce82921a2fd500, stable, linux-mm, linux-kernel, kernel-team, Matt Fleming On 24 Jul 2026, at 16:26, Zi Yan wrote: > Use Lorenzo’s current email. > > On 24 Jul 2026, at 16:18, Zi Yan wrote: > >> On 24 Jul 2026, at 15:52, Matt Fleming wrote: >> >>> From: Matt Fleming <mfleming@cloudflare.com> >>> >>> xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but >>> __folio_split() leaves the xa_state's xa_lru unset. That lets a live, >> >> But mapping_set_update() is not required for xas_split_alloc() and xas_split(), >> or at least nothing triggered for uniform split path. Why? >> >> xas_split_alloc() uses >> gfp = current_gfp_context(mapping_gfp_mask(mapping) & GFP_RECLAIM_MASK), >> whereas xas_try_split() starts with GFP_NOWAIT and follows xas_nomem() >> by adding __GFP_ACCOUNT if XA_FLAGS_ACCOUNT is set. >> >> Should xas_split_alloc() also take a gfp input and the caller gets >> gfp the same way as xas_split_alloc()? xas_try_split() is called under the xarray lock with irq disabled, so it cannot accept arbitrary gfp. And xas_split_alloc() is the only one does not do if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) gfp |= __GFP_ACCOUNT; the others, xas_nomem(), __xas_nomem(), and xas_alloc() all have it. Commit 7b785645e8f13 ("mm: fix page cache convergence regression") added the __GFP_ACCOUNT statement. I will send a patch to add it to xas_split_alloc() with Fixes: 6b24ca4a1a8d4 ("mm: Use multi-index entries in the page cache") In sum, I think this patch does the right thing. And Sashiko pointed out this issue before[1]. [1] https://sashiko.dev/#/patchset/20260716095424.471052-1-kirill@shutemov.name >> >>> memcg-charged xa_node exist without being linked into the mapping's >>> shadow_nodes list_lru; when reclaim later walks the list_lru it trips >>> VM_WARN_ON(!css_is_dying()). >>> >>> Use mapping_set_update() to install both the workingset update callback >>> and the shadow_nodes list_lru on the xa_state. >>> >>> Reported-by: syzbot+c5b060ce82921a2fd500@syzkaller.appspotmail.com >>> Closes: https://syzkaller.appspot.com/bug?extid=c5b060ce82921a2fd500 >>> Fixes: 58729c04cf10 ("mm/huge_memory: add buddy allocator like (non-uniform) folio_split()") >>> Cc: stable@vger.kernel.org >>> Signed-off-by: Matt Fleming <mfleming@cloudflare.com> >>> --- >>> mm/huge_memory.c | 3 ++- >>> 1 file changed, 2 insertions(+), 1 deletion(-) >>> >>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >>> index b5d1e9d4463d..12d0e0b14e83 100644 >>> --- a/mm/huge_memory.c >>> +++ b/mm/huge_memory.c >>> @@ -4033,7 +4033,8 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >>> gfp_t gfp; >>> >>> mapping = folio->mapping; >>> - min_order = mapping_min_folio_order(folio->mapping); >>> + mapping_set_update(&xas, mapping); >>> + min_order = mapping_min_folio_order(mapping); >>> if (new_order < min_order) { >>> ret = -EINVAL; >>> goto out; >>> -- >>> 2.43.0 mapping_set_update() probably can be delayed right before the if block containing xas_split_alloc(). Otherwise, LGTM. Thanks. Reviewed-by: Zi Yan <ziy@nvidia.com> Best Regards, Yan, Zi ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-25 3:16 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-07-24 19:52 [PATCH] mm/huge_memory: Initialise workingset state before folio split Matt Fleming 2026-07-24 20:18 ` Zi Yan 2026-07-24 20:26 ` Zi Yan 2026-07-25 3:16 ` Zi Yan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®