diff options
author | Hugh Dickins <hughd@google.com> | 2019-04-18 20:49:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-19 12:46:04 -0400 |
commit | 87039546544479d4bedb19d0ea525270c43c1c9b (patch) | |
tree | 0520eeb66e4c3d8fa9e80f7b0b42fbaa4f8fd90b /mm/shmem.c | |
parent | 1a62b18d51e5c5ecc0345c85bb9fef870ab721ed (diff) |
mm: swapoff: shmem_find_swap_entries() filter out other types
Swapfile "type" was passed all the way down to shmem_unuse_inode(), but
then forgotten from shmem_find_swap_entries(): with the result that
removing one swapfile would try to free up all the swap from shmem - no
problem when only one swapfile anyway, but counter-productive when more,
causing swapoff to be unnecessarily OOM-killed when it should succeed.
Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1904081254470.1523@eggly.anvils
Fixes: b56a2d8af914 ("mm: rid swapoff of quadratic complexity")
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Cc: "Alex Xu (Hello71)" <alex_y_xu@yahoo.ca>
Cc: Vineeth Pillai <vpillai@digitalocean.com>
Cc: Kelley Nielsen <kelleynnn@gmail.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Huang Ying <ying.huang@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index b3db3779a30a..859e8628071f 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1099,10 +1099,11 @@ extern struct swap_info_struct *swap_info[]; | |||
1099 | static int shmem_find_swap_entries(struct address_space *mapping, | 1099 | static int shmem_find_swap_entries(struct address_space *mapping, |
1100 | pgoff_t start, unsigned int nr_entries, | 1100 | pgoff_t start, unsigned int nr_entries, |
1101 | struct page **entries, pgoff_t *indices, | 1101 | struct page **entries, pgoff_t *indices, |
1102 | bool frontswap) | 1102 | unsigned int type, bool frontswap) |
1103 | { | 1103 | { |
1104 | XA_STATE(xas, &mapping->i_pages, start); | 1104 | XA_STATE(xas, &mapping->i_pages, start); |
1105 | struct page *page; | 1105 | struct page *page; |
1106 | swp_entry_t entry; | ||
1106 | unsigned int ret = 0; | 1107 | unsigned int ret = 0; |
1107 | 1108 | ||
1108 | if (!nr_entries) | 1109 | if (!nr_entries) |
@@ -1116,13 +1117,12 @@ static int shmem_find_swap_entries(struct address_space *mapping, | |||
1116 | if (!xa_is_value(page)) | 1117 | if (!xa_is_value(page)) |
1117 | continue; | 1118 | continue; |
1118 | 1119 | ||
1119 | if (frontswap) { | 1120 | entry = radix_to_swp_entry(page); |
1120 | swp_entry_t entry = radix_to_swp_entry(page); | 1121 | if (swp_type(entry) != type) |
1121 | 1122 | continue; | |
1122 | if (!frontswap_test(swap_info[swp_type(entry)], | 1123 | if (frontswap && |
1123 | swp_offset(entry))) | 1124 | !frontswap_test(swap_info[type], swp_offset(entry))) |
1124 | continue; | 1125 | continue; |
1125 | } | ||
1126 | 1126 | ||
1127 | indices[ret] = xas.xa_index; | 1127 | indices[ret] = xas.xa_index; |
1128 | entries[ret] = page; | 1128 | entries[ret] = page; |
@@ -1194,7 +1194,7 @@ static int shmem_unuse_inode(struct inode *inode, unsigned int type, | |||
1194 | 1194 | ||
1195 | pvec.nr = shmem_find_swap_entries(mapping, start, nr_entries, | 1195 | pvec.nr = shmem_find_swap_entries(mapping, start, nr_entries, |
1196 | pvec.pages, indices, | 1196 | pvec.pages, indices, |
1197 | frontswap); | 1197 | type, frontswap); |
1198 | if (pvec.nr == 0) { | 1198 | if (pvec.nr == 0) { |
1199 | ret = 0; | 1199 | ret = 0; |
1200 | break; | 1200 | break; |