Skip to contentSkip to conversation

xarray: honor XA_FLAGS_ACCOUNT in xas_split_alloc()

RFC PATCH Superseded Zi Yan 2 participants 3 messages Jul 28 – Jul 30

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Zi Yan

author
#0 lore raw

RFC PATCH 1/1 xarray: honor XA_FLAGS_ACCOUNT in xas_split_alloc()

XArray operations that allocate xa_nodes, such as xas_nomem() and xas_alloc(), add __GFP_ACCOUNT when the array has XA_FLAGS_ACCOUNT set. This charges the allocated memory and avoids the workingset convergence issue described by commit 7b785645e8f13 ("mm: fix page cache convergence regression").

xas_split_alloc() does not have that flag. Add it when necessary.

Fixes 6b24ca4a1a8d4 ("mm: Use multi-index entries in the page cache")

---
Hi Johannes,

IIUC, __GFP_ACCOUNT is needed for xarray node allocation accounting when XA_FLAGS_ACCOUNT is set. Commit 7b785645e8f13 ("mm: fix page cache convergence regression") fixed a workingset regression with it. xas_split_alloc() does not have it, so I imagine xa_node allocated during folio split would cause a similar issue. I would like to get your opinion on this.

Thanks.

This patch, if necessary, should be applied on top of the mapping_set_update() fix[1] to avoid causing the same issue for uniform split path.

---
 lib/xarray.c | 3 +++
 1 file changed, 3 insertions(+)
lib/xarray.c +3 -0
index 9a8b4916540cf..bfe7bef80f34e 100644
@@ -1053,6 +1053,9 @@ void xas_split_alloc(struct xa_state *xas, void *entry, unsigned int order,
 	if (xas->xa_shift + XA_CHUNK_SHIFT > order)
 		return;
 
+	if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT)
+		gfp |= __GFP_ACCOUNT;
+
 	do {
 		struct xa_node *node;
 

---
base-commit: 34cacd0ac7c10dc9e34e1b9f28a2b78d335cb487
change-id: 20260727-add-gfp_account-to-xas_split_alloc-83a1bc848b77

Best regards,

Signature · 1 line
Yan, Zi
#1 lore raw

Hello Zi,

Quoted 13 lines · Zi Yan

XArray operations that allocate xa_nodes, such as xas_nomem() and xas_alloc(), add __GFP_ACCOUNT when the array has XA_FLAGS_ACCOUNT set. This charges the allocated memory and avoids the workingset convergence issue described by commit 7b785645e8f13 ("mm: fix page cache convergence regression").

xas_split_alloc() does not have that flag. Add it when necessary.

Fixes 6b24ca4a1a8d4 ("mm: Use multi-index entries in the page cache")

---
Hi Johannes,

Quoted 6 lines

IIUC, __GFP_ACCOUNT is needed for xarray node allocation accounting when XA_FLAGS_ACCOUNT is set. Commit 7b785645e8f13 ("mm: fix page cache convergence regression") fixed a workingset regression with it. xas_split_alloc() does not have it, so I imagine xa_node allocated during folio split would cause a similar issue. I would like to get your opinion on this.

Yes, you're right!

As we had discussed on the THP cabal call, we should use the memcg context of the folio, as that could be different from the callers' depending on who's doing the splitting. I.e.

	memcg = get_mem_cgroup_from_folio(x);
	old_memcg = set_active_memcg(memcg);

	xas_split_alloc() / xas_try_split()

	set_active_memcg(old_memcg);
	mem_cgroup_put(memcg);

There is __folio_split() -> xas_split_alloc(). But there is also __folio_split() -> __folio_freeze_and_split_unmapped() -> __split_unmapped_folio() -> xas_try_split() -> XA_FLAGS_ACCOUNT -> __GFP_ACCOUNT. So it would make sense to me to set up the memcg context in __folio_split() already.

author
#2 lore raw
Quoted 37 lines · Johannes Weiner

Hello Zi,

Quoted 13 lines · Zi Yan

XArray operations that allocate xa_nodes, such as xas_nomem() and xas_alloc(), add __GFP_ACCOUNT when the array has XA_FLAGS_ACCOUNT set. This charges the allocated memory and avoids the workingset convergence issue described by commit 7b785645e8f13 ("mm: fix page cache convergence regression").

xas_split_alloc() does not have that flag. Add it when necessary.

Fixes 6b24ca4a1a8d4 ("mm: Use multi-index entries in the page cache")

---
Hi Johannes,

Quoted 6 lines

IIUC, __GFP_ACCOUNT is needed for xarray node allocation accounting when XA_FLAGS_ACCOUNT is set. Commit 7b785645e8f13 ("mm: fix page cache convergence regression") fixed a workingset regression with it. xas_split_alloc() does not have it, so I imagine xa_node allocated during folio split would cause a similar issue. I would like to get your opinion on this.

Yes, you're right!

As we had discussed on the THP cabal call, we should use the memcg context of the folio, as that could be different from the callers' depending on who's doing the splitting. I.e.

	memcg = get_mem_cgroup_from_folio(x);
	old_memcg = set_active_memcg(memcg);

	xas_split_alloc() / xas_try_split()

	set_active_memcg(old_memcg);
	mem_cgroup_put(memcg);
Quoted 5 lines

There is __folio_split() -> xas_split_alloc(). But there is also __folio_split() -> __folio_freeze_and_split_unmapped() -> __split_unmapped_folio() -> xas_try_split() -> XA_FLAGS_ACCOUNT -> __GFP_ACCOUNT. So it would make sense to me to set up the memcg context in __folio_split() already.

Thank you for the detailed analysis. Will add memcg context code and send a new version.

Best Regards,
Yan, Zi