Commit 65018076 authored by Baolin Wang's avatar Baolin Wang Committed by Andrew Morton

mm: swap: extend swap_shmem_alloc() to support batch SWAP_MAP_SHMEM flag setting

Patch series "support large folio swap-out and swap-in for shmem", v5.

Shmem will support large folio allocation [1] [2] to get a better
performance, however, the memory reclaim still splits the precious large
folios when trying to swap-out shmem, which may lead to the memory
fragmentation issue and can not take advantage of the large folio for
shmeme.

Moreover, the swap code already supports for swapping out large folio
without split, and large folio swap-in[3] series is queued into
mm-unstable branch.  Hence this patch set also supports the large folio
swap-out and swap-in for shmem.


This patch (of 9):

To support shmem large folio swap operations, add a new parameter to
swap_shmem_alloc() that allows batch SWAP_MAP_SHMEM flag setting for shmem
swap entries.

While we are at it, using folio_nr_pages() to get the number of pages of
the folio as a preparation.

Link: https://lkml.kernel.org/r/cover.1723434324.git.baolin.wang@linux.alibaba.com
Link: https://lkml.kernel.org/r/99f64115d04b285e009580eb177352c57119ffd0.1723434324.git.baolin.wang@linux.alibaba.comSigned-off-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
Reviewed-by: default avatarBarry Song <baohua@kernel.org>
Cc: Chris Li <chrisl@kernel.org>
Cc: Daniel Gomez <da.gomez@samsung.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: "Huang, Ying" <ying.huang@intel.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Cc: Lance Yang <ioworker0@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pankaj Raghav <p.raghav@samsung.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Yang Shi <shy828301@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent bea67dcc
...@@ -481,7 +481,7 @@ void put_swap_folio(struct folio *folio, swp_entry_t entry); ...@@ -481,7 +481,7 @@ void put_swap_folio(struct folio *folio, swp_entry_t entry);
extern swp_entry_t get_swap_page_of_type(int); extern swp_entry_t get_swap_page_of_type(int);
extern int get_swap_pages(int n, swp_entry_t swp_entries[], int order); extern int get_swap_pages(int n, swp_entry_t swp_entries[], int order);
extern int add_swap_count_continuation(swp_entry_t, gfp_t); extern int add_swap_count_continuation(swp_entry_t, gfp_t);
extern void swap_shmem_alloc(swp_entry_t); extern void swap_shmem_alloc(swp_entry_t, int);
extern int swap_duplicate(swp_entry_t); extern int swap_duplicate(swp_entry_t);
extern int swapcache_prepare(swp_entry_t entry, int nr); extern int swapcache_prepare(swp_entry_t entry, int nr);
extern void swap_free_nr(swp_entry_t entry, int nr_pages); extern void swap_free_nr(swp_entry_t entry, int nr_pages);
...@@ -548,7 +548,7 @@ static inline int add_swap_count_continuation(swp_entry_t swp, gfp_t gfp_mask) ...@@ -548,7 +548,7 @@ static inline int add_swap_count_continuation(swp_entry_t swp, gfp_t gfp_mask)
return 0; return 0;
} }
static inline void swap_shmem_alloc(swp_entry_t swp) static inline void swap_shmem_alloc(swp_entry_t swp, int nr)
{ {
} }
......
...@@ -1452,6 +1452,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) ...@@ -1452,6 +1452,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
swp_entry_t swap; swp_entry_t swap;
pgoff_t index; pgoff_t index;
int nr_pages;
/* /*
* Our capabilities prevent regular writeback or sync from ever calling * Our capabilities prevent regular writeback or sync from ever calling
...@@ -1484,6 +1485,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) ...@@ -1484,6 +1485,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
} }
index = folio->index; index = folio->index;
nr_pages = folio_nr_pages(folio);
/* /*
* This is somewhat ridiculous, but without plumbing a SWAP_MAP_FALLOC * This is somewhat ridiculous, but without plumbing a SWAP_MAP_FALLOC
...@@ -1536,8 +1538,8 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) ...@@ -1536,8 +1538,8 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
if (add_to_swap_cache(folio, swap, if (add_to_swap_cache(folio, swap,
__GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN, __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN,
NULL) == 0) { NULL) == 0) {
shmem_recalc_inode(inode, 0, 1); shmem_recalc_inode(inode, 0, nr_pages);
swap_shmem_alloc(swap); swap_shmem_alloc(swap, nr_pages);
shmem_delete_from_page_cache(folio, swp_to_radix_entry(swap)); shmem_delete_from_page_cache(folio, swp_to_radix_entry(swap));
mutex_unlock(&shmem_swaplist_mutex); mutex_unlock(&shmem_swaplist_mutex);
......
...@@ -3657,9 +3657,9 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr) ...@@ -3657,9 +3657,9 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
* Help swapoff by noting that swap entry belongs to shmem/tmpfs * Help swapoff by noting that swap entry belongs to shmem/tmpfs
* (in which case its reference count is never incremented). * (in which case its reference count is never incremented).
*/ */
void swap_shmem_alloc(swp_entry_t entry) void swap_shmem_alloc(swp_entry_t entry, int nr)
{ {
__swap_duplicate(entry, SWAP_MAP_SHMEM, 1); __swap_duplicate(entry, SWAP_MAP_SHMEM, nr);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment