SHM_UNLOCK: fix Unevictable pages stranded after swap
Hugh Dickins authored
commit 24513264 upstream.

Commit cc39c6a9

 ("mm: account skipped entries to avoid looping in
find_get_pages") correctly fixed an infinite loop; but left a problem
that find_get_pages() on shmem would return 0 (appearing to callers to
mean end of tree) when it meets a run of nr_pages swap entries.

The only uses of find_get_pages() on shmem are via pagevec_lookup(),
called from invalidate_mapping_pages(), and from shmctl SHM_UNLOCK's
scan_mapping_unevictable_pages().  The first is already commented, and
not worth worrying about; but the second can leave pages on the
Unevictable list after an unusual sequence of swapping and locking.

Fix that by using shmem_find_get_pages_and_swap() (then ignoring the
swap) instead of pagevec_lookup().

But I don't want to contaminate vmscan.c with shmem internals, nor
shmem.c with LRU locking.  So move scan_mapping_unevictable_pages() into
shmem.c, renaming it shmem_unlock_mapping(); and rename
check_move_unevictable_page() to check_move_unevictable_pages(), looping
down an array of pages, oftentimes under the same lock.

Leave out the "rotate unevictable list" block: that's a leftover from
when this was used for /proc/sys/vm/scan_unevictable_pages, whose flawed
handling involved looking at pages at tail of LRU.

Was there significance to the sequence first ClearPageUnevictable, then
test page_evictable, then SetPageUnevictable here? I think not, we're
under LRU lock, and have no barriers between those.
Signed-off-by: default avatarHugh Dickins <hughd@google.com>
Reviewed-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Shaohua Li <shaohua.li@intel.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michel Lespinasse <walken@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
4556a6d9
Name Last commit Last update
..
Kconfig memblock: add NO_BOOTMEM config symbol
Kconfig.debug mm: debug-pagealloc: fix kconfig dependency warning
Makefile Cross Memory Attach
backing-dev.c backing-dev: ensure wakeup_timer is deleted
bootmem.c mm: Map most files to use export.h instead of module.h
bounce.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
cleancache.c mm: cleancache core ops functions and config
compaction.c mm: compaction: make compact_zone_order() static
debug-pagealloc.c debug-pagealloc: add support for highmem pages
dmapool.c mm: fix implicit stat.h usage in dmapool.c
fadvise.c readahead: introduce FMODE_RANDOM for POSIX_FADV_RANDOM
failslab.c fault-injection: add ability to export fault_attr in arbitrary directory
filemap.c memcg: add mem_cgroup_replace_page_cache() to fix LRU issue
filemap_xip.c mm: Map most files to use export.h instead of module.h
fremap.c mm: delete various needless include <linux/module.h>
highmem.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
huge_memory.c thp: reduce khugepaged freezing latency
hugetlb.c mm: hugetlb: fix non-atomic enqueue of huge page
hwpoison-inject.c Fix common misspellings
init-mm.c atomic: use <linux/atomic.h>
internal.h mm: thp: tail page refcounting fix
kmemcheck.c kmemcheck: add hooks for the page allocator
kmemleak-test.c kmemleak: remove memset by using kzalloc
kmemleak.c mm: Map most files to use export.h instead of module.h
ksm.c oom: fix race while temporarily setting current's oom_score_adj
maccess.c mm: Map most files to use export.h instead of module.h
madvise.c fs: kill i_alloc_sem
memblock.c mm/memblock.c: quiet sparse noise
memcontrol.c memcg: add mem_cgroup_replace_page_cache() to fix LRU issue
memory-failure.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
memory.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
memory_hotplug.c mm: Map most files to use export.h instead of module.h
mempolicy.c mm/mempolicy.c: refix mbind_range() vma issue
mempool.c mm: Map most files to use export.h instead of module.h
migrate.c mm/migrate.c: pair unlock_page() and lock_page() when migrating huge pages
mincore.c mm: clarify the radix_tree exceptional cases
mlock.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
mm_init.c mm: Map most files to use export.h instead of module.h
mmap.c Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux
mmu_context.c mm: Map most files to use export.h instead of module.h
mmu_notifier.c mm: Map most files to use export.h instead of module.h
mmzone.c mm: delete various needless include <linux/module.h>
mprotect.c thp: mprotect: transparent huge page support
mremap.c thp: mremap support and TLB optimization
msync.c sanitize vfs_fsync calling conventions
nobootmem.c mm: Map most files to use export.h instead of module.h
nommu.c xen: map foreign pages for shared rings by updating the PTEs directly
oom_kill.c oom: fix integer overflow of points in oom_badness
page-writeback.c writeback: set max_pause to lowest value on zero bdi_dirty
page_alloc.c mm: fix NULL ptr dereference in __count_immobile_pages
page_cgroup.c
page_io.c
page_isolation.c
pagewalk.c
percpu-km.c
percpu-vm.c
percpu.c
pgtable-generic.c
prio_tree.c
process_vm_access.c
quicklist.c
readahead.c
rmap.c
shmem.c
slab.c
slob.c
slub.c
sparse-vmemmap.c
sparse.c
swap.c
swap_state.c
swapfile.c
thrash.c
truncate.c
util.c
vmalloc.c
vmscan.c
vmstat.c