Commit 40ff2d11 authored by Baolin Wang's avatar Baolin Wang Committed by Andrew Morton

mm: shmem: use swap_free_nr() to free shmem swap entries

As a preparation for supporting shmem large folio swapout, use
swap_free_nr() to free some continuous swap entries of the shmem large
folio when the large folio was swapped in from the swap cache.  In
addition, the index should also be round down to the number of pages when
adding the swapin folio into the pagecache.

Link: https://lkml.kernel.org/r/342207fa679fc88a447dac2e101ad79e6050fe79.1723434324.git.baolin.wang@linux.alibaba.comSigned-off-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry 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 fb724159
...@@ -1961,6 +1961,7 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index, ...@@ -1961,6 +1961,7 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index,
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
swp_entry_t swapin_error; swp_entry_t swapin_error;
void *old; void *old;
int nr_pages;
swapin_error = make_poisoned_swp_entry(); swapin_error = make_poisoned_swp_entry();
old = xa_cmpxchg_irq(&mapping->i_pages, index, old = xa_cmpxchg_irq(&mapping->i_pages, index,
...@@ -1969,6 +1970,7 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index, ...@@ -1969,6 +1970,7 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index,
if (old != swp_to_radix_entry(swap)) if (old != swp_to_radix_entry(swap))
return; return;
nr_pages = folio_nr_pages(folio);
folio_wait_writeback(folio); folio_wait_writeback(folio);
delete_from_swap_cache(folio); delete_from_swap_cache(folio);
/* /*
...@@ -1976,8 +1978,8 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index, ...@@ -1976,8 +1978,8 @@ static void shmem_set_folio_swapin_error(struct inode *inode, pgoff_t index,
* won't be 0 when inode is released and thus trigger WARN_ON(i_blocks) * won't be 0 when inode is released and thus trigger WARN_ON(i_blocks)
* in shmem_evict_inode(). * in shmem_evict_inode().
*/ */
shmem_recalc_inode(inode, -1, -1); shmem_recalc_inode(inode, -nr_pages, -nr_pages);
swap_free(swap); swap_free_nr(swap, nr_pages);
} }
/* /*
...@@ -1996,7 +1998,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, ...@@ -1996,7 +1998,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
struct swap_info_struct *si; struct swap_info_struct *si;
struct folio *folio = NULL; struct folio *folio = NULL;
swp_entry_t swap; swp_entry_t swap;
int error; int error, nr_pages;
VM_BUG_ON(!*foliop || !xa_is_value(*foliop)); VM_BUG_ON(!*foliop || !xa_is_value(*foliop));
swap = radix_to_swp_entry(*foliop); swap = radix_to_swp_entry(*foliop);
...@@ -2043,6 +2045,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, ...@@ -2043,6 +2045,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
goto failed; goto failed;
} }
folio_wait_writeback(folio); folio_wait_writeback(folio);
nr_pages = folio_nr_pages(folio);
/* /*
* Some architectures may have to restore extra metadata to the * Some architectures may have to restore extra metadata to the
...@@ -2056,19 +2059,20 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, ...@@ -2056,19 +2059,20 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
goto failed; goto failed;
} }
error = shmem_add_to_page_cache(folio, mapping, index, error = shmem_add_to_page_cache(folio, mapping,
round_down(index, nr_pages),
swp_to_radix_entry(swap), gfp); swp_to_radix_entry(swap), gfp);
if (error) if (error)
goto failed; goto failed;
shmem_recalc_inode(inode, 0, -1); shmem_recalc_inode(inode, 0, -nr_pages);
if (sgp == SGP_WRITE) if (sgp == SGP_WRITE)
folio_mark_accessed(folio); folio_mark_accessed(folio);
delete_from_swap_cache(folio); delete_from_swap_cache(folio);
folio_mark_dirty(folio); folio_mark_dirty(folio);
swap_free(swap); swap_free_nr(swap, nr_pages);
put_swap_device(si); put_swap_device(si);
*foliop = folio; *foliop = folio;
......
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