summaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2019-04-18 20:49:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-04-19 12:46:04 -0400
commit87039546544479d4bedb19d0ea525270c43c1c9b (patch)
tree0520eeb66e4c3d8fa9e80f7b0b42fbaa4f8fd90b /mm/shmem.c
parent1a62b18d51e5c5ecc0345c85bb9fef870ab721ed (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.c18
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[];
1099static int shmem_find_swap_entries(struct address_space *mapping, 1099static 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;