mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/8] mm: remove page_swap_entry()
@ 2026-08-30 10:32 Tal Zussman
  2026-08-30 10:32 ` [PATCH 1/8] mm/swap: add folio_swap_entry() and folio_page_swap_entry() Tal Zussman
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

A folio in the swap cache occupies folio_nr_pages() contiguous swap
entries starting at folio->swap, so a page's swap entry is just
folio->swap plus the page's index in the folio. The swap entry is
folio state, but the only helper for it is page-based:
page_swap_entry() takes a page and recomputes the folio its callers
already hold. Several callers avoid it by open-coding the arithmetic
on folio->swap instead.

Add folio_swap_entry() and folio_page_swap_entry(), convert all users,
and remove page_swap_entry(), with a few other cleanups along the way.

---
Tal Zussman (8):
      mm/swap: add folio_swap_entry() and folio_page_swap_entry()
      mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio
      mm/rmap: use folio_page_swap_entry() in ttu_anon_swapbacked_folio()
      mm/zswap: convert the store path to take a folio and index
      mm/swapfile: use folio_page_swap_entry()
      arm64: mte: make mte_save_tags() and mte_restore_tags() static
      arm64: mte: pass the swap entry to mte_save_tags()
      mm/swap: remove page_swap_entry()

 arch/arm64/include/asm/mte.h |  2 --
 arch/arm64/mm/mteswap.c      | 32 ++++++++++++++------------------
 include/linux/swap.h         | 30 +++++++++++++++++++++++++++---
 mm/huge_memory.c             |  2 +-
 mm/rmap.c                    |  2 +-
 mm/swapfile.c                |  4 ++--
 mm/zswap.c                   | 25 +++++++++++--------------
 7 files changed, 56 insertions(+), 41 deletions(-)
---
base-commit: da6c37ed8beb273e3308e42d4bca3ce11b4432fa
change-id: 20260807-folio_swap_entry-e53d68610de0

Best regards,
--  
Tal Zussman <tz2294@columbia.edu>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/8] mm/swap: add folio_swap_entry() and folio_page_swap_entry()
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio Tal Zussman
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

A folio in the swap cache occupies folio_nr_pages() contiguous swap
entries starting at folio->swap, so a page's swap entry is just
folio->swap plus the page's index in the folio. page_swap_entry() hides
this behind a compound_head() call, and callers that already have the
folio sometimes open-code the arithmetic instead.

Add folio_swap_entry(), which takes a folio and a page index, and
folio_page_swap_entry() for callers that have the page.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 include/linux/swap.h | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0f953ed9c863..48632aacbc2a 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -278,6 +278,39 @@ struct swap_info_struct {
 	const struct swap_ops *ops;
 };
 
+/**
+ * folio_swap_entry - Return the swap entry for a page within a folio.
+ * @folio: The folio.
+ * @idx: The index of the page within the folio.
+ *
+ * A folio in the swap cache occupies folio_nr_pages() contiguous swap
+ * entries starting at folio->swap. The caller must ensure the folio is
+ * in the swap cache and that @idx is within the folio.
+ */
+static inline
+swp_entry_t folio_swap_entry(const struct folio *folio, unsigned long idx)
+{
+	swp_entry_t entry = folio->swap;
+
+	VM_WARN_ON_ONCE_FOLIO(idx >= folio_nr_pages(folio), folio);
+	entry.val += idx;
+	return entry;
+}
+
+/**
+ * folio_page_swap_entry - Return the swap entry of a page in a folio.
+ * @folio: The folio containing @page.
+ * @page: A page within @folio.
+ *
+ * The caller must ensure the folio is in the swap cache and that @page
+ * is part of @folio.
+ */
+static inline swp_entry_t folio_page_swap_entry(const struct folio *folio,
+		const struct page *page)
+{
+	return folio_swap_entry(folio, folio_page_idx(folio, page));
+}
+
 static inline swp_entry_t page_swap_entry(struct page *page)
 {
 	struct folio *folio = page_folio(page);

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
  2026-08-30 10:32 ` [PATCH 1/8] mm/swap: add folio_swap_entry() and folio_page_swap_entry() Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-31 14:50   ` Zi Yan
  2026-08-30 10:32 ` [PATCH 3/8] mm/rmap: use folio_page_swap_entry() in ttu_anon_swapbacked_folio() Tal Zussman
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

__split_folio_to_order() open-codes the swap entry computation for the
split-out folios. Use folio_swap_entry() instead.

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 mm/huge_memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 54494c3fa983..03287f995d92 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3760,7 +3760,7 @@ static void __split_folio_to_order(struct folio *folio, int old_order,
 		VM_WARN_ON_ONCE_PAGE(new_folio->private, new_head);
 
 		if (folio_test_swapcache(folio))
-			new_folio->swap.val = folio->swap.val + i;
+			new_folio->swap = folio_swap_entry(folio, i);
 
 		/* Page flags must be visible before we make the page non-compound. */
 		smp_wmb();

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/8] mm/rmap: use folio_page_swap_entry() in ttu_anon_swapbacked_folio()
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
  2026-08-30 10:32 ` [PATCH 1/8] mm/swap: add folio_swap_entry() and folio_page_swap_entry() Tal Zussman
  2026-08-30 10:32 ` [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 4/8] mm/zswap: convert the store path to take a folio and index Tal Zussman
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

We already have the folio here, so use folio_page_swap_entry() instead
of going through page_swap_entry(). This saves a call to
compound_head().

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 mm/rmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index fed0362e0bd0..ef34126c6ce8 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -2143,7 +2143,7 @@ static bool ttu_anon_swapbacked_folio(struct vm_area_struct *vma,
 {
 	const bool anon_exclusive = folio_test_anon(folio) &&
 				    PageAnonExclusive(page);
-	swp_entry_t entry = page_swap_entry(page);
+	swp_entry_t entry = folio_page_swap_entry(folio, page);
 	struct mm_struct *mm = vma->vm_mm;
 
 	if (folio_dup_swap(folio, page) < 0)

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 4/8] mm/zswap: convert the store path to take a folio and index
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
                   ` (2 preceding siblings ...)
  2026-08-30 10:32 ` [PATCH 3/8] mm/rmap: use folio_page_swap_entry() in ttu_anon_swapbacked_folio() Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 5/8] mm/swapfile: use folio_page_swap_entry() Tal Zussman
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

zswap_store_page() and zswap_compress() take a page that zswap_store()
just derived from a folio, then convert back to a folio for the swap
entry, memcg, and node. Pass the folio and page index down instead, and
use sg_set_folio() and kmap_local_folio(). zswap_decompress() already
takes a folio, so this also makes the two paths match.

This removes the last struct page usage from the zswap store path and
saves two calls to compound_head().

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 mm/zswap.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/mm/zswap.c b/mm/zswap.c
index f3ae3c81e48e..3a6f89017646 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -824,8 +824,8 @@ static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)
 	return ret;
 }
 
-static bool zswap_compress(struct page *page, struct zswap_entry *entry,
-			   struct zswap_pool *pool)
+static bool zswap_compress(struct folio *folio, long index,
+			   struct zswap_entry *entry, struct zswap_pool *pool)
 {
 	struct crypto_acomp_ctx *acomp_ctx;
 	struct scatterlist input, output;
@@ -841,7 +841,7 @@ static bool zswap_compress(struct page *page, struct zswap_entry *entry,
 
 	dst = acomp_ctx->buffer;
 	sg_init_table(&input, 1);
-	sg_set_page(&input, page, PAGE_SIZE, 0);
+	sg_set_folio(&input, folio, PAGE_SIZE, index * PAGE_SIZE);
 
 	sg_init_one(&output, dst, PAGE_SIZE);
 	acomp_request_set_params(acomp_ctx->req, &input, &output, PAGE_SIZE, dlen);
@@ -870,8 +870,7 @@ static bool zswap_compress(struct page *page, struct zswap_entry *entry,
 	 */
 	if (comp_ret || !dlen || dlen >= PAGE_SIZE) {
 		rcu_read_lock();
-		if (!mem_cgroup_zswap_writeback_enabled(
-					folio_memcg(page_folio(page)))) {
+		if (!mem_cgroup_zswap_writeback_enabled(folio_memcg(folio))) {
 			rcu_read_unlock();
 			comp_ret = comp_ret ? comp_ret : -EINVAL;
 			goto unlock;
@@ -879,12 +878,12 @@ static bool zswap_compress(struct page *page, struct zswap_entry *entry,
 		rcu_read_unlock();
 		comp_ret = 0;
 		dlen = PAGE_SIZE;
-		dst = kmap_local_page(page);
+		dst = kmap_local_folio(folio, index * PAGE_SIZE);
 		mapped = true;
 	}
 
 	gfp = GFP_NOWAIT | __GFP_NORETRY | __GFP_HIGHMEM | __GFP_MOVABLE;
-	handle = zs_malloc(pool->zs_pool, dlen, gfp, page_to_nid(page));
+	handle = zs_malloc(pool->zs_pool, dlen, gfp, folio_nid(folio));
 	if (IS_ERR_VALUE(handle)) {
 		alloc_ret = PTR_ERR((void *)handle);
 		goto unlock;
@@ -1392,21 +1391,21 @@ static void shrink_worker(struct work_struct *w)
 * main API
 **********************************/
 
-static bool zswap_store_page(struct page *page,
+static bool zswap_store_page(struct folio *folio, long index,
 			     struct obj_cgroup *objcg,
 			     struct zswap_pool *pool)
 {
-	swp_entry_t page_swpentry = page_swap_entry(page);
+	swp_entry_t page_swpentry = folio_swap_entry(folio, index);
 	struct zswap_entry *entry, *old;
 
 	/* allocate entry */
-	entry = zswap_entry_cache_alloc(GFP_KERNEL, page_to_nid(page));
+	entry = zswap_entry_cache_alloc(GFP_KERNEL, folio_nid(folio));
 	if (!entry) {
 		zswap_reject_kmemcache_fail++;
 		return false;
 	}
 
-	if (!zswap_compress(page, entry, pool))
+	if (!zswap_compress(folio, index, entry, pool))
 		goto compress_failed;
 
 	old = xa_store(swap_zswap_tree(page_swpentry),
@@ -1515,9 +1514,7 @@ bool zswap_store(struct folio *folio)
 	}
 
 	for (index = 0; index < nr_pages; ++index) {
-		struct page *page = folio_page(folio, index);
-
-		if (!zswap_store_page(page, objcg, pool))
+		if (!zswap_store_page(folio, index, objcg, pool))
 			goto put_pool;
 	}
 

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 5/8] mm/swapfile: use folio_page_swap_entry()
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
                   ` (3 preceding siblings ...)
  2026-08-30 10:32 ` [PATCH 4/8] mm/zswap: convert the store path to take a folio and index Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 6/8] arm64: mte: make mte_save_tags() and mte_restore_tags() static Tal Zussman
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

folio_dup_swap() and folio_put_swap() open-code the swap entry
computation from folio->swap and folio_page_idx(). Use
folio_page_swap_entry() instead.

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 mm/swapfile.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 58db70424253..c7b8e69a1227 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1810,7 +1810,7 @@ int folio_dup_swap(struct folio *folio, struct page *page)
 	VM_WARN_ON_FOLIO(!folio_test_swapcache(folio), folio);
 
 	if (page) {
-		entry.val += folio_page_idx(folio, page);
+		entry = folio_page_swap_entry(folio, page);
 		nr_pages = 1;
 	}
 
@@ -1837,7 +1837,7 @@ void folio_put_swap(struct folio *folio, struct page *page)
 	VM_WARN_ON_FOLIO(!folio_test_swapcache(folio), folio);
 
 	if (page) {
-		entry.val += folio_page_idx(folio, page);
+		entry = folio_page_swap_entry(folio, page);
 		nr_pages = 1;
 	}
 

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 6/8] arm64: mte: make mte_save_tags() and mte_restore_tags() static
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
                   ` (4 preceding siblings ...)
  2026-08-30 10:32 ` [PATCH 5/8] mm/swapfile: use folio_page_swap_entry() Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 7/8] arm64: mte: pass the swap entry to mte_save_tags() Tal Zussman
  2026-08-30 10:32 ` [PATCH 8/8] mm/swap: remove page_swap_entry() Tal Zussman
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

mte_save_tags() and mte_restore_tags() are only used by
arch_prepare_to_swap() and arch_swap_restore() in mteswap.c. Make them
static and remove their declarations from mte.h.

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 arch/arm64/include/asm/mte.h | 2 --
 arch/arm64/mm/mteswap.c      | 4 ++--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
index 7f7b97e09996..83f3b05fc784 100644
--- a/arch/arm64/include/asm/mte.h
+++ b/arch/arm64/include/asm/mte.h
@@ -23,9 +23,7 @@ unsigned long mte_copy_tags_from_user(void *to, const void __user *from,
 				      unsigned long n);
 unsigned long mte_copy_tags_to_user(void __user *to, void *from,
 				    unsigned long n);
-int mte_save_tags(struct page *page);
 void mte_save_page_tags(const void *page_addr, void *tag_storage);
-void mte_restore_tags(swp_entry_t entry, struct page *page);
 void mte_restore_page_tags(void *page_addr, const void *tag_storage);
 void mte_invalidate_tags(int type, pgoff_t offset);
 void mte_invalidate_tags_area(int type);
diff --git a/arch/arm64/mm/mteswap.c b/arch/arm64/mm/mteswap.c
index 63e8d72f202a..3c54afc8b758 100644
--- a/arch/arm64/mm/mteswap.c
+++ b/arch/arm64/mm/mteswap.c
@@ -20,7 +20,7 @@ void mte_free_tag_storage(char *storage)
 	kfree(storage);
 }
 
-int mte_save_tags(struct page *page)
+static int mte_save_tags(struct page *page)
 {
 	void *tag_storage, *ret;
 
@@ -47,7 +47,7 @@ int mte_save_tags(struct page *page)
 	return 0;
 }
 
-void mte_restore_tags(swp_entry_t entry, struct page *page)
+static void mte_restore_tags(swp_entry_t entry, struct page *page)
 {
 	void *tags = xa_load(&mte_pages, entry.val);
 

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 7/8] arm64: mte: pass the swap entry to mte_save_tags()
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
                   ` (5 preceding siblings ...)
  2026-08-30 10:32 ` [PATCH 6/8] arm64: mte: make mte_save_tags() and mte_restore_tags() static Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  2026-08-30 10:32 ` [PATCH 8/8] mm/swap: remove page_swap_entry() Tal Zussman
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

arch_prepare_to_swap() derives a page from the folio only for
mte_save_tags() to recompute the folio's swap entry from that page.
Pass the entry in directly with folio_swap_entry(), matching
mte_restore_tags(), and move the page_mte_tagged() check into the
caller so we only compute the entry for tagged pages.

__mte_invalidate_tags() loses its only user, so remove it and call
mte_invalidate_tags() directly in the error path. This removes two
calls to compound_head().

No functional change.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 arch/arm64/mm/mteswap.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/mm/mteswap.c b/arch/arm64/mm/mteswap.c
index 3c54afc8b758..f64202b69309 100644
--- a/arch/arm64/mm/mteswap.c
+++ b/arch/arm64/mm/mteswap.c
@@ -20,22 +20,17 @@ void mte_free_tag_storage(char *storage)
 	kfree(storage);
 }
 
-static int mte_save_tags(struct page *page)
+static int mte_save_tags(swp_entry_t entry, struct page *page)
 {
 	void *tag_storage, *ret;
 
-	if (!page_mte_tagged(page))
-		return 0;
-
 	tag_storage = mte_allocate_tag_storage();
 	if (!tag_storage)
 		return -ENOMEM;
 
 	mte_save_page_tags(page_address(page), tag_storage);
 
-	/* lookup the swap entry.val from the page */
-	ret = xa_store(&mte_pages, page_swap_entry(page).val, tag_storage,
-		       GFP_KERNEL);
+	ret = xa_store(&mte_pages, entry.val, tag_storage, GFP_KERNEL);
 	if (WARN(xa_is_err(ret), "Failed to store MTE tags")) {
 		mte_free_tag_storage(tag_storage);
 		return xa_err(ret);
@@ -68,13 +63,6 @@ void mte_invalidate_tags(int type, pgoff_t offset)
 	mte_free_tag_storage(tags);
 }
 
-static inline void __mte_invalidate_tags(struct page *page)
-{
-	swp_entry_t entry = page_swap_entry(page);
-
-	mte_invalidate_tags(swp_type(entry), swp_offset(entry));
-}
-
 void mte_invalidate_tags_area(int type)
 {
 	swp_entry_t entry = swp_entry(type, 0);
@@ -102,15 +90,23 @@ int arch_prepare_to_swap(struct folio *folio)
 	nr = folio_nr_pages(folio);
 
 	for (i = 0; i < nr; i++) {
-		err = mte_save_tags(folio_page(folio, i));
+		struct page *page = folio_page(folio, i);
+
+		if (!page_mte_tagged(page))
+			continue;
+
+		err = mte_save_tags(folio_swap_entry(folio, i), page);
 		if (err)
 			goto out;
 	}
 	return 0;
 
 out:
-	while (i--)
-		__mte_invalidate_tags(folio_page(folio, i));
+	while (i--) {
+		swp_entry_t swap = folio_swap_entry(folio, i);
+
+		mte_invalidate_tags(swp_type(swap), swp_offset(swap));
+	}
 	return err;
 }
 

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 8/8] mm/swap: remove page_swap_entry()
  2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
                   ` (6 preceding siblings ...)
  2026-08-30 10:32 ` [PATCH 7/8] arm64: mte: pass the swap entry to mte_save_tags() Tal Zussman
@ 2026-08-30 10:32 ` Tal Zussman
  7 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-30 10:32 UTC (permalink / raw)
  To: Andrew Morton, Chris Li, Kairui Song, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, David Hildenbrand, Zi Yan,
	Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain,
	Lance Yang, Usama Arif, Kiryl Shutsemau, Lorenzo Stoakes,
	Rik van Riel, Vlastimil Babka, Harry Yoo, Jann Horn,
	Johannes Weiner, Yosry Ahmed, Chengming Zhou, Catalin Marinas,
	Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel, Tal Zussman

All callers have been converted to folio_swap_entry() and
folio_page_swap_entry(), so remove it.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 include/linux/swap.h | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 48632aacbc2a..2fa436958fdb 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -311,15 +311,6 @@ static inline swp_entry_t folio_page_swap_entry(const struct folio *folio,
 	return folio_swap_entry(folio, folio_page_idx(folio, page));
 }
 
-static inline swp_entry_t page_swap_entry(struct page *page)
-{
-	struct folio *folio = page_folio(page);
-	swp_entry_t entry = folio->swap;
-
-	entry.val += folio_page_idx(folio, page);
-	return entry;
-}
-
 /* linux/mm/page_alloc.c */
 extern unsigned long totalreserve_pages;
 

-- 
2.39.5


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio
  2026-08-30 10:32 ` [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio Tal Zussman
@ 2026-08-31 14:50   ` Zi Yan
  2026-08-31 23:38     ` Tal Zussman
  0 siblings, 1 reply; 11+ messages in thread
From: Zi Yan @ 2026-08-31 14:50 UTC (permalink / raw)
  To: Tal Zussman, Andrew Morton, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, Barry Song, Youngjun Park,
	David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache,
	Ryan Roberts, Dev Jain, Lance Yang, Usama Arif, Kiryl Shutsemau,
	Lorenzo Stoakes, Rik van Riel, Vlastimil Babka, Harry Yoo,
	Jann Horn, Johannes Weiner, Yosry Ahmed, Chengming Zhou,
	Catalin Marinas, Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel

On Sun Aug 30, 2026 at 6:32 AM EDT, Tal Zussman wrote:
> __split_folio_to_order() open-codes the swap entry computation for the
> split-out folios. Use folio_swap_entry() instead.
>
> No functional change.
>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
> ---
>  mm/huge_memory.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 54494c3fa983..03287f995d92 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -3760,7 +3760,7 @@ static void __split_folio_to_order(struct folio *folio, int old_order,
>  		VM_WARN_ON_ONCE_PAGE(new_folio->private, new_head);
>  
>  		if (folio_test_swapcache(folio))
> -			new_folio->swap.val = folio->swap.val + i;
> +			new_folio->swap = folio_swap_entry(folio, i);

folio_swap_entry() checks folio_nr_pages(folio) internally.
folio->_nr_pages is in first tail page of folio. If new_order is 0, it
is basically checking memcg_data in the first new_folio. And after first
iteration, folio->_nr_page will be clobbered. Without
NR_PAGES_IN_LARGE_FOLIO, folio_nr_pages() is derived from folio_order(),
which is in folio->_flags_1. It can have the same issue.

Please keep it open coded. You can add a comment like "during split,
not all folio fields are avaialbe, open code the swap calculation".

>  
>  		/* Page flags must be visible before we make the page non-compound. */
>  		smp_wmb();

-- 
Best Regards,
Yan, Zi


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio
  2026-08-31 14:50   ` Zi Yan
@ 2026-08-31 23:38     ` Tal Zussman
  0 siblings, 0 replies; 11+ messages in thread
From: Tal Zussman @ 2026-08-31 23:38 UTC (permalink / raw)
  To: Zi Yan, Andrew Morton, Chris Li, Kairui Song, Kemeng Shi,
	Nhat Pham, Baoquan He, Barry Song, Youngjun Park,
	David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache,
	Ryan Roberts, Dev Jain, Lance Yang, Usama Arif, Kiryl Shutsemau,
	Lorenzo Stoakes, Rik van Riel, Vlastimil Babka, Harry Yoo,
	Jann Horn, Johannes Weiner, Yosry Ahmed, Chengming Zhou,
	Catalin Marinas, Will Deacon, Mark Rutland
  Cc: linux-mm, linux-kernel, linux-arm-kernel

On 8/31/26 5:50 PM, Zi Yan wrote:
> On Sun Aug 30, 2026 at 6:32 AM EDT, Tal Zussman wrote:
>> __split_folio_to_order() open-codes the swap entry computation for the
>> split-out folios. Use folio_swap_entry() instead.
>>
>> No functional change.
>>
>> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
>> ---
>>  mm/huge_memory.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
>> index 54494c3fa983..03287f995d92 100644
>> --- a/mm/huge_memory.c
>> +++ b/mm/huge_memory.c
>> @@ -3760,7 +3760,7 @@ static void __split_folio_to_order(struct folio *folio, int old_order,
>>  		VM_WARN_ON_ONCE_PAGE(new_folio->private, new_head);
>>  
>>  		if (folio_test_swapcache(folio))
>> -			new_folio->swap.val = folio->swap.val + i;
>> +			new_folio->swap = folio_swap_entry(folio, i);
> 
> folio_swap_entry() checks folio_nr_pages(folio) internally.
> folio->_nr_pages is in first tail page of folio. If new_order is 0, it
> is basically checking memcg_data in the first new_folio. And after first
> iteration, folio->_nr_page will be clobbered. Without
> NR_PAGES_IN_LARGE_FOLIO, folio_nr_pages() is derived from folio_order(),
> which is in folio->_flags_1. It can have the same issue.
> 
> Please keep it open coded. You can add a comment like "during split,
> not all folio fields are avaialbe, open code the swap calculation".
> 

Thanks, I'll drop this change.

I was debating whether the warning was worth adding. It'd be nice to
avoid accessing swap.val directly and abstract it away, but given that
that's done in a few other places too, open-coding it is fine.

>>  
>>  		/* Page flags must be visible before we make the page non-compound. */
>>  		smp_wmb();
> 
> -- 
> Best Regards,
> Yan, Zi
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-08-31 23:38 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-30 10:32 [PATCH 0/8] mm: remove page_swap_entry() Tal Zussman
2026-08-30 10:32 ` [PATCH 1/8] mm/swap: add folio_swap_entry() and folio_page_swap_entry() Tal Zussman
2026-08-30 10:32 ` [PATCH 2/8] mm/huge_memory: use folio_swap_entry() when splitting a swapcache folio Tal Zussman
2026-08-31 14:50   ` Zi Yan
2026-08-31 23:38     ` Tal Zussman
2026-08-30 10:32 ` [PATCH 3/8] mm/rmap: use folio_page_swap_entry() in ttu_anon_swapbacked_folio() Tal Zussman
2026-08-30 10:32 ` [PATCH 4/8] mm/zswap: convert the store path to take a folio and index Tal Zussman
2026-08-30 10:32 ` [PATCH 5/8] mm/swapfile: use folio_page_swap_entry() Tal Zussman
2026-08-30 10:32 ` [PATCH 6/8] arm64: mte: make mte_save_tags() and mte_restore_tags() static Tal Zussman
2026-08-30 10:32 ` [PATCH 7/8] arm64: mte: pass the swap entry to mte_save_tags() Tal Zussman
2026-08-30 10:32 ` [PATCH 8/8] mm/swap: remove page_swap_entry() Tal Zussman

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®