Commit 87039546 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds
Browse files

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: b56a2d8a ("mm: rid swapoff of quadratic complexity")
Signed-off-by: default avatarHugh 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1a62b18d
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -1099,10 +1099,11 @@ extern struct swap_info_struct *swap_info[];
static int shmem_find_swap_entries(struct address_space *mapping,
				   pgoff_t start, unsigned int nr_entries,
				   struct page **entries, pgoff_t *indices,
				   bool frontswap)
				   unsigned int type, bool frontswap)
{
	XA_STATE(xas, &mapping->i_pages, start);
	struct page *page;
	swp_entry_t entry;
	unsigned int ret = 0;

	if (!nr_entries)
@@ -1116,13 +1117,12 @@ static int shmem_find_swap_entries(struct address_space *mapping,
		if (!xa_is_value(page))
			continue;

		if (frontswap) {
			swp_entry_t entry = radix_to_swp_entry(page);

			if (!frontswap_test(swap_info[swp_type(entry)],
					    swp_offset(entry)))
		entry = radix_to_swp_entry(page);
		if (swp_type(entry) != type)
			continue;
		if (frontswap &&
		    !frontswap_test(swap_info[type], swp_offset(entry)))
			continue;
		}

		indices[ret] = xas.xa_index;
		entries[ret] = page;
@@ -1194,7 +1194,7 @@ static int shmem_unuse_inode(struct inode *inode, unsigned int type,

		pvec.nr = shmem_find_swap_entries(mapping, start, nr_entries,
						  pvec.pages, indices,
						  frontswap);
						  type, frontswap);
		if (pvec.nr == 0) {
			ret = 0;
			break;