Mike Kravetz
9c34ad0ce3
mm: migration: fix migration of huge PMD shared pages
...
commit 017b1660df89f5fb4bfe66c34e35f7d2031100c7 upstream.
The page migration code employs try_to_unmap() to try and unmap the source
page. This is accomplished by using rmap_walk to find all vmas where the
page is mapped. This search stops when page mapcount is zero. For shared
PMD huge pages, the page map count is always 1 no matter the number of
mappings. Shared mappings are tracked via the reference count of the PMD
page. Therefore, try_to_unmap stops prematurely and does not completely
unmap all mappings of the source page.
This problem can result is data corruption as writes to the original
source page can happen after contents of the page are copied to the target
page. Hence, data is lost.
This problem was originally seen as DB corruption of shared global areas
after a huge page was soft offlined due to ECC memory errors. DB
developers noticed they could reproduce the issue by (hotplug) offlining
memory used to back huge pages. A simple testcase can reproduce the
problem by creating a shared PMD mapping (note that this must be at least
PUD_SIZE in size and PUD_SIZE aligned (1GB on x86)), and using
migrate_pages() to migrate process pages between nodes while continually
writing to the huge pages being migrated.
To fix, have the try_to_unmap_one routine check for huge PMD sharing by
calling huge_pmd_unshare for hugetlbfs huge pages. If it is a shared
mapping it will be 'unshared' which removes the page table entry and drops
the reference on the PMD page. After this, flush caches and TLB.
mmu notifiers are called before locking page tables, but we can not be
sure of PMD sharing until page tables are locked. Therefore, check for
the possibility of PMD sharing before locking so that notifiers can
prepare for the worst possible case.
Link: http://lkml.kernel.org/r/20180823205917.16297-2-mike.kravetz@oracle.com
[mike.kravetz@oracle.com: make _range_in_vma() a static inline]
Link: http://lkml.kernel.org/r/6063f215-a5c8-2f0c-465a-2c515ddc952d@oracle.com
Fixes: 39dde65c99 ("shared page table for hugetlb page")
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Reviewed-by: Jérôme Glisse <jglisse@redhat.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-11-21 09:26:03 +01:00
..
kasan
kasan: fix shadow_size calculation error in kasan_module_alloc
2018-08-24 13:12:35 +02:00
backing-dev.c
block: fix double-free in the failure path of cgwb_bdi_init()
2017-02-26 11:10:52 +01:00
balloon_compaction.c
mm: balloon: use general non-lru movable page feature
2016-07-26 16:19:19 -07:00
bootmem.c
mm: kmemleak: avoid using __va() on addresses that don't have a lowmem mapping
2016-10-11 15:06:33 -07:00
cleancache.c
cleancache: constify cleancache_ops structure
2016-01-27 09:09:57 -05:00
cma.c
cma: fix calculation of aligned offset
2018-01-31 12:55:51 +01:00
cma.h
mm: cma: mark cma_bitmap_maxno() inline in header
2015-08-14 15:56:32 -07:00
cma_debug.c
mm/cma_debug: correct size input to bitmap function
2015-07-17 16:39:54 -07:00
compaction.c
mm, compaction: fix NR_ISOLATED_* stats for pfn based migration
2017-01-12 11:39:32 +01:00
debug.c
mm: get rid of vmacache_flush_all() entirely
2018-09-19 22:47:17 +02:00
debug_page_ref.c
mm/page_ref: add tracepoint to track down page reference manipulation
2016-03-17 15:09:34 -07:00
dmapool.c
mm: convert printk(KERN_<LEVEL> to pr_<level>
2016-03-17 15:09:34 -07:00
early_ioremap.c
mm/early_ioremap: Fix boot hang with earlyprintk=efi,keep
2018-02-25 11:05:49 +01:00
fadvise.c
mm/fadvise.c: fix signed overflow UBSAN complaint
2018-09-15 09:42:57 +02:00
failslab.c
mm: fault-inject take over bootstrap kmem_cache check
2016-03-15 16:55:16 -07:00
filemap.c
mm/filemap.c: fix NULL pointer in page_cache_tree_insert()
2018-04-24 09:34:18 +02:00
frame_vector.c
mm/frame_vector.c: release a semaphore in 'get_vaddr_frames()'
2018-11-10 07:42:52 -08:00
frontswap.c
mm, frontswap: convert frontswap_enabled to static key
2016-07-26 16:19:19 -07:00
gup.c
mm: do not bug_on on incorrect length in __mm_populate()
2018-11-21 09:25:58 +01:00
highmem.c
mm/highmem: make nr_free_highpages() handles all highmem zones by itself
2016-05-19 19:12:14 -07:00
huge_memory.c
mremap: properly flush TLB before releasing the page
2018-10-20 09:51:31 +02:00
hugetlb.c
mm: migration: fix migration of huge PMD shared pages
2018-11-21 09:26:03 +01:00
hugetlb_cgroup.c
mm, hugetlb_cgroup: round limit_in_bytes down to hugepage size
2016-05-20 17:58:30 -07:00
hwpoison-inject.c
hwpoison: use page_cgroup_ino for filtering by memcg
2015-09-10 13:29:01 -07:00
init-mm.c
mm: Add a user_ns owner to mm_struct and fix ptrace permission checks
2017-01-06 10:40:13 +01:00
internal.h
mm: fix 100% CPU kswapd busyloop on unreclaimable nodes
2018-01-31 12:55:53 +01:00
interval_tree.c
Kconfig
mm: don't allow deferred pages with NEED_PER_CPU_KM
2018-05-22 16:57:57 +02:00
Kconfig.debug
PM / Hibernate: allow hibernation with PAGE_POISONING_ZERO
2016-09-13 02:35:27 +02:00
khugepaged.c
mm, thp: do not cause memcg oom for thp
2018-05-30 07:50:38 +02:00
kmemcheck.c
mm: convert printk(KERN_<LEVEL> to pr_<level>
2016-03-17 15:09:34 -07:00
kmemleak-test.c
mm: convert printk(KERN_<LEVEL> to pr_<level>
2016-03-17 15:09:34 -07:00
kmemleak.c
mm/kmemleak.c: wait for scan completion before disabling free
2018-05-30 07:50:39 +02:00
ksm.c
mm/ksm: fix interaction with THP
2018-05-30 07:50:41 +02:00
list_lru.c
mm/list_lru.c: fix list_lru_count_node() to be race free
2017-07-21 07:42:21 +02:00
maccess.c
x86: remove more uaccess_32.h complexity
2016-05-22 17:21:27 -07:00
madvise.c
mm: madvise(MADV_DODUMP): allow hugetlbfs pages
2018-10-10 08:53:20 +02:00
Makefile
Disable the __builtin_return_address() warning globally after all
2016-10-12 10:23:41 -07:00
memblock.c
mm/memblock.c: reversed logic in memblock_discard()
2017-08-30 10:21:47 +02:00
memcontrol.c
memcg: remove memcg_cgroup::id from IDR on mem_cgroup_css_alloc() failure
2018-09-05 09:20:04 +02:00
memory-failure.c
mm: hwpoison: call shake_page() after try_to_unmap() for mlocked page
2018-03-24 11:00:21 +01:00
memory.c
mm/tlb: Remove tlb_remove_table() non-concurrent condition
2018-09-09 20:01:23 +02:00
memory_hotplug.c
mm/memory_hotplug.c: fix overflow in test_pages_in_a_zone()
2018-11-10 07:42:44 -08:00
mempolicy.c
mm: thp: relax __GFP_THISNODE for MADV_HUGEPAGE mappings
2018-11-21 09:26:00 +01:00
mempool.c
Revert "mm, mempool: only set __GFP_NOMEMALLOC if there are free elements"
2016-07-28 16:07:41 -07:00
memtest.c
memtest: remove unused header files
2015-09-08 15:35:28 -07:00
migrate.c
Sanitize 'move_pages()' permission checks
2017-08-24 17:12:21 -07:00
mincore.c
mm, swap: use offset of swap entry as key of swap cache
2016-10-07 18:46:28 -07:00
mlock.c
mlock: fix mlock count can not decrease in race condition
2017-06-07 12:07:49 +02:00
mm_init.c
mm: convert printk(KERN_<LEVEL> to pr_<level>
2016-03-17 15:09:34 -07:00
mmap.c
mm: do not bug_on on incorrect length in __mm_populate()
2018-11-21 09:25:58 +01:00
mmu_context.c
mm/mmu_context, sched/core: Fix mmu_context.h assumption
2016-04-28 11:44:19 +02:00
mmu_notifier.c
fix Christoph's email addresses
2016-03-17 15:09:34 -07:00
mmzone.c
mm, page_alloc: inline the fast path of the zonelist iterator
2016-05-19 19:12:14 -07:00
mprotect.c
x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings
2018-08-15 18:14:45 +02:00
mremap.c
mremap: properly flush TLB before releasing the page
2018-10-20 09:51:31 +02:00
msync.c
mm/msync: use offset_in_page macro
2015-11-05 19:34:48 -08:00
nobootmem.c
mm: discard memblock data later
2017-08-24 17:12:19 -07:00
nommu.c
ptrace: Don't allow accessing an undumpable mm
2017-01-06 10:40:13 +01:00
oom_kill.c
mm, oom_reaper: gather each vma to prevent leaking TLB entry
2017-12-09 22:01:47 +01:00
page-writeback.c
writeback: safer lock nesting
2018-04-24 09:34:18 +02:00
page_alloc.c
mm, page_alloc: do not break __GFP_THISNODE by zonelist reset
2018-07-11 16:26:45 +02:00
page_counter.c
mm: page_counter: let page_counter_try_charge() return bool
2015-11-05 19:34:48 -08:00
page_ext.c
mm/page_ext: support extra space allocation by page_ext user
2016-10-07 18:46:27 -07:00
page_idle.c
mm, vmscan: move lru_lock to the node
2016-07-28 16:07:41 -07:00
page_io.c
mm/page_io.c: replace some BUG_ON()s with VM_BUG_ON_PAGE()
2016-10-07 18:46:29 -07:00
page_isolation.c
mm/page_isolation: fix typo: "paes" -> "pages"
2016-10-07 18:46:29 -07:00
page_owner.c
mm/page_owner: don't define fields on struct page_ext by hard-coding
2016-10-07 18:46:27 -07:00
page_poison.c
mm: check the return value of lookup_page_ext for all call sites
2016-06-03 15:06:22 -07:00
pagewalk.c
mm/pagewalk.c: report holes in hugetlb ranges
2017-11-24 08:33:42 +01:00
percpu-km.c
mm: percpu: use pr_fmt to prefix output
2016-03-17 15:09:34 -07:00
percpu-vm.c
percpu.c
percpu: include linux/sched.h for cond_resched()
2018-05-09 09:50:18 +02:00
pgtable-generic.c
mm/thp/migration: switch from flush_tlb_range to flush_pmd_tlb_range
2016-03-17 15:09:34 -07:00
process_vm_access.c
mm: remove write/force parameters from __get_user_pages_unlocked()
2016-10-18 14:13:37 -07:00
quicklist.c
fix Christoph's email addresses
2016-03-17 15:09:34 -07:00
readahead.c
mm: silently skip readahead for DAX inodes
2016-08-26 17:39:35 -07:00
rmap.c
mm: migration: fix migration of huge PMD shared pages
2018-11-21 09:26:03 +01:00
shmem.c
mm: shmem.c: Correctly annotate new inodes for lockdep
2018-09-29 03:07:32 -07:00
slab.c
mm, slab: reschedule cache_reap() on the same CPU
2018-04-24 09:34:09 +02:00
slab.h
slub: move synchronize_sched out of slab_mutex on shrink
2017-03-22 12:43:38 +01:00
slab_common.c
slub: do not merge cache if slub_debug contains a never-merge flag
2017-10-21 17:21:36 +02:00
slob.c
slub: move synchronize_sched out of slab_mutex on shrink
2017-03-22 12:43:38 +01:00
slub.c
slub: make ->cpu_partial unsigned int
2018-10-03 17:01:50 -07:00
sparse-vmemmap.c
treewide: replace obsolete _refok by __ref
2016-08-02 17:31:41 -04:00
sparse.c
mm/memory_hotplug: set magic number to page->freelist instead of page->lru.next
2017-10-21 17:21:36 +02:00
swap.c
thp: reduce usage of huge zero page's atomic counter
2016-10-07 18:46:28 -07:00
swap_cgroup.c
mm, swap_cgroup: reschedule when neeed in swap_cgroup_swapoff()
2017-07-05 14:40:17 +02:00
swap_state.c
mm, swap: use offset of swap entry as key of swap cache
2016-10-07 18:46:28 -07:00
swapfile.c
x86/speculation/l1tf: Limit swap file size to MAX_PA/2
2018-08-15 18:14:45 +02:00
truncate.c
fs: add i_blocksize()
2017-06-14 15:06:00 +02:00
usercopy.c
mm: usercopy: Check for module addresses
2016-09-20 16:07:39 -07:00
userfaultfd.c
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
2016-04-04 10:41:08 -07:00
util.c
Provide a function to create a NUL-terminated string from unterminated data
2018-02-25 11:05:41 +01:00
vmacache.c
mm: get rid of vmacache_flush_all() entirely
2018-09-19 22:47:17 +02:00
vmalloc.c
mm: vmalloc: avoid racy handling of debugobjects in vunmap
2018-08-03 07:55:13 +02:00
vmpressure.c
mm: vmpressure: fix sending wrong events on underflow
2017-03-12 06:41:43 +01:00
vmscan.c
mm: remove seemingly spurious reclaimability check from laptop_mode gating
2018-09-19 22:47:12 +02:00
vmstat.c
mm/vmstat.c: fix outdated vmstat_text
2018-10-18 09:13:21 +02:00
workingset.c
mm: workingset: fix premature shadow node shrinking with cgroups
2017-04-08 09:30:36 +02:00
z3fold.c
mm/z3fold.c: avoid modifying HEADLESS page and minor cleanup
2016-06-03 16:02:55 -07:00
zbud.c
mm/zbud.c: use list_last_entry() instead of list_tail_entry()
2016-01-15 11:40:52 -08:00
zpool.c
mm: zsmalloc: constify struct zs_pool name
2015-11-06 17:50:42 -08:00
zsmalloc.c
zsmalloc: calling zs_map_object() from irq is a bug
2017-12-14 09:28:23 +01:00
zswap.c
zswap: re-check zswap_is_full() after do zswap_shrink()
2018-09-05 09:20:02 +02:00