From: Dev Jain <dev.jain@arm.com>
To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org,
hughd@google.com, chrisl@kernel.org, kasong@tencent.com
Cc: Dev Jain <dev.jain@arm.com>,
riel@surriel.com, liam@infradead.org, vbabka@kernel.org,
harry@kernel.org, jannh@google.com, lance.yang@linux.dev,
baolin.wang@linux.alibaba.com, shikemeng@huaweicloud.com,
nphamcs@gmail.com, baoquan.he@linux.dev, baohua@kernel.org,
youngjun.park@lge.com, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, rppt@kernel.org, surenb@google.com,
mhocko@suse.com, pfalcato@suse.de, ryan.roberts@arm.com,
anshuman.khandual@arm.com
Subject: [PATCH v2 2/8] mm/swapfile: add batched version of folio_put_swap
Date: Tue, 1 Sep 2026 05:43:49 +0000 [thread overview]
Message-ID: <20260901054358.4049095-3-dev.jain@arm.com> (raw)
In-Reply-To: <20260901054358.4049095-1-dev.jain@arm.com>
Add folio_put_swap_pages to handle a batch of consecutive pages. Note
that folio_put_swap already can handle a subset of this: nr_pages == 1 and
nr_pages == folio_nr_pages(folio). Generalize this to any nr_pages.
Currently we have a not-so-nice logic of passing in subpage == NULL if
we mean to exercise the logic on the entire folio, and subpage != NULL if
we want to exercise the logic on only that subpage. Remove this
indirection: the caller invokes folio_put_swap_pages() if it wants to
operate on a range of pages in the folio (i.e nr_pages may be anything
between 1 and folio_nr_pages()), and invokes folio_put_swap() if it
wants to operate on the entire folio.
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Dev Jain <dev.jain@arm.com>
Reviewed-by: Barry Song <baohua@kernel.org>
---
mm/memory.c | 6 +++---
mm/rmap.c | 4 ++--
mm/shmem.c | 6 +++---
mm/swap.h | 17 +++++++++++++++--
mm/swapfile.c | 19 ++++++++++---------
5 files changed, 33 insertions(+), 19 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 8b0c2c735d3de..6cfea4faf0588 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5202,7 +5202,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
if (unlikely(folio != swapcache)) {
folio_add_new_anon_rmap(folio, vma, address, RMAP_EXCLUSIVE);
folio_add_lru_vma(folio, vma);
- folio_put_swap(swapcache, NULL);
+ folio_put_swap(swapcache);
} else if (!folio_test_anon(folio)) {
/*
* We currently only expect !anon folios that are fully
@@ -5211,12 +5211,12 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
VM_WARN_ON_ONCE_FOLIO(folio_nr_pages(folio) != nr_pages, folio);
VM_WARN_ON_ONCE_FOLIO(folio_mapped(folio), folio);
folio_add_new_anon_rmap(folio, vma, address, rmap_flags);
- folio_put_swap(folio, NULL);
+ folio_put_swap(folio);
} else {
VM_WARN_ON_ONCE(nr_pages != 1 && nr_pages != folio_nr_pages(folio));
folio_add_anon_rmap_ptes(folio, page, nr_pages, vma, address,
rmap_flags);
- folio_put_swap(folio, nr_pages == 1 ? page : NULL);
+ folio_put_swap_pages(folio, page, nr_pages);
}
VM_BUG_ON(!folio_test_anon(folio) ||
diff --git a/mm/rmap.c b/mm/rmap.c
index 0a4aa06b66de6..1b9f07d4d1be9 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -2157,13 +2157,13 @@ static bool ttu_anon_swapbacked_folio(struct vm_area_struct *vma,
* so we'll not check/care.
*/
if (arch_unmap_one(mm, vma, address, pteval) < 0) {
- folio_put_swap(folio, page);
+ folio_put_swap_pages(folio, page, 1);
return false;
}
/* See folio_try_share_anon_rmap(): clear PTE first. */
if (anon_exclusive && folio_try_share_anon_rmap_pte(folio, page)) {
- folio_put_swap(folio, page);
+ folio_put_swap_pages(folio, page, 1);
return false;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 6cea018d69f04..316bf14136d63 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1733,7 +1733,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
/* Swap entry might be erased by racing shmem_free_swap() */
if (!error) {
shmem_recalc_inode(inode, 0, -nr_pages);
- folio_put_swap(folio, NULL);
+ folio_put_swap(folio);
}
/*
@@ -2163,7 +2163,7 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index,
nr_pages = folio_nr_pages(folio);
folio_wait_writeback(folio);
- folio_put_swap(folio, NULL);
+ folio_put_swap(folio);
swap_cache_del_folio(folio);
/*
* Don't treat swapin error folio as alloced. Otherwise inode->i_blocks
@@ -2393,7 +2393,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
if (sgp == SGP_WRITE)
folio_mark_accessed(folio);
- folio_put_swap(folio, NULL);
+ folio_put_swap(folio);
swap_cache_del_folio(folio);
folio_mark_dirty(folio);
put_swap_device(si);
diff --git a/mm/swap.h b/mm/swap.h
index f52ecbedae8b8..0e0d00bf4daa6 100644
--- a/mm/swap.h
+++ b/mm/swap.h
@@ -246,7 +246,8 @@ extern int swap_retry_table_alloc(swp_entry_t entry, gfp_t gfp);
int folio_alloc_swap(struct folio *folio);
int folio_dup_swap_pages(struct folio *folio, struct page *page,
unsigned long nr_pages);
-void folio_put_swap(struct folio *folio, struct page *page);
+void folio_put_swap_pages(struct folio *folio, struct page *page,
+ unsigned long nr_pages);
/* For internal use */
extern void __swap_cluster_free_entries(struct swap_info_struct *si,
@@ -375,7 +376,8 @@ static inline int folio_dup_swap_pages(struct folio *folio, struct page *page,
return -EINVAL;
}
-static inline void folio_put_swap(struct folio *folio, struct page *page)
+static inline void folio_put_swap_pages(struct folio *folio, struct page *page,
+ unsigned long nr_pages)
{
}
@@ -477,6 +479,17 @@ static inline int folio_dup_swap(struct folio *folio)
folio_nr_pages(folio));
}
+/**
+ * folio_put_swap() - Decrease swap count of all swap entries of a folio.
+ * @folio: folio with swap entries bound.
+ *
+ * See folio_put_swap_pages() for more information.
+ */
+static inline void folio_put_swap(struct folio *folio)
+{
+ folio_put_swap_pages(folio, folio_page(folio, 0), folio_nr_pages(folio));
+}
+
extern const struct swap_ops swap_bdev_ops;
int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 25bb6fc562c57..da5e66bdcef10 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1819,27 +1819,27 @@ int folio_dup_swap_pages(struct folio *folio, struct page *page,
}
/**
- * folio_put_swap() - Decrease swap count of swap entries of a folio.
+ * folio_put_swap_pages() - Decrease swap count of swap entries of a folio.
* @folio: folio with swap entries bounded, must be in swap cache and locked.
- * @page: if not NULL, only decrease the swap count of this page.
+ * @page: the first page in the folio to decrease the swap count for.
+ * @nr_pages: the number of pages in the folio to decrease the swap count for.
*
* This won't free the swap slots even if swap count drops to zero, they are
* still pinned by the swap cache. User may call folio_free_swap to free them.
* Context: Caller must ensure the folio is locked and in the swap cache.
*/
-void folio_put_swap(struct folio *folio, struct page *page)
+void folio_put_swap_pages(struct folio *folio, struct page *page,
+ unsigned long nr_pages)
{
swp_entry_t entry = folio->swap;
- unsigned long nr_pages = folio_nr_pages(folio);
struct swap_info_struct *si = __swap_entry_to_info(entry);
+ unsigned long idx = folio_page_idx(folio, page);
VM_WARN_ON_FOLIO(!folio_test_locked(folio), folio);
VM_WARN_ON_FOLIO(!folio_test_swapcache(folio), folio);
+ VM_WARN_ON_FOLIO(idx + nr_pages > folio_nr_pages(folio), folio);
- if (page) {
- entry.val += folio_page_idx(folio, page);
- nr_pages = 1;
- }
+ entry.val += idx;
swap_put_entries_cluster(si, swp_offset(entry), nr_pages, false);
}
@@ -2518,7 +2518,8 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
setpte:
set_pte_at(vma->vm_mm, addr, pte, new_pte);
- folio_put_swap(swapcache, folio_file_page(swapcache, swp_offset(entry)));
+ folio_put_swap_pages(swapcache,
+ folio_file_page(swapcache, swp_offset(entry)), 1);
out:
if (pte)
pte_unmap_unlock(pte, ptl);
--
2.43.0
next prev parent reply other threads:[~2026-09-01 5:44 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 5:43 [PATCH v2 0/8] Optimize anonymous swapbacked large folio unmapping Dev Jain
2026-09-01 5:43 ` [PATCH v2 1/8] mm/swapfile: add batched version of folio_dup_swap Dev Jain
2026-09-01 5:43 ` Dev Jain [this message]
2026-09-01 5:43 ` [PATCH v2 3/8] mm: move anon-exclusive batch helper to mm.h Dev Jain
2026-09-01 5:49 ` Barry Song
2026-09-01 6:24 ` Dev Jain
2026-09-02 6:29 ` Barry Song
2026-09-04 3:46 ` Dev Jain
2026-09-01 5:43 ` [PATCH v2 4/8] mm/rmap: Add batched version of folio_try_share_anon_rmap_pte Dev Jain
[not found] ` <CAGsJ_4zWPXoJ5kiLoVcq1YHv6WcmjPEssTUs4OT15iNRob3_rQ@mail.gmail.com>
2026-09-09 7:44 ` Dev Jain
2026-09-01 5:43 ` [PATCH v2 5/8] mm/internal: rename swap offset helpers to softleaf offset Dev Jain
2026-09-05 10:42 ` Barry Song
2026-09-05 10:49 ` Barry Song
2026-09-07 5:38 ` Dev Jain
2026-09-07 21:33 ` Barry Song
2026-09-08 5:38 ` Dev Jain
2026-09-08 8:41 ` Garg, Shivank
2026-09-01 5:43 ` [PATCH v2 6/8] mm/internal: add set_softleaf_ptes Dev Jain
2026-09-05 10:52 ` Barry Song
2026-09-01 5:43 ` [PATCH v2 7/8] mm/memory: use set_softleaf_ptes for uffd-wp markers Dev Jain
2026-09-05 10:53 ` Barry Song
2026-09-01 5:43 ` [PATCH v2 8/8] mm/rmap: batch unmap anonymous swap-backed large folios Dev Jain
2026-09-08 21:48 ` Barry Song
2026-09-10 4:39 ` Dev Jain
2026-09-10 4:58 ` Barry Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260901054358.4049095-3-dev.jain@arm.com \
--to=dev.jain@arm.com \
--cc=akpm@linux-foundation.org \
--cc=anshuman.khandual@arm.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=chrisl@kernel.org \
--cc=david@kernel.org \
--cc=harry@kernel.org \
--cc=hughd@google.com \
--cc=jannh@google.com \
--cc=kasong@tencent.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=nphamcs@gmail.com \
--cc=pfalcato@suse.de \
--cc=riel@surriel.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=shikemeng@huaweicloud.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=youngjun.park@lge.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.