From: Greg Kroah-Hartman Date: Mon, 3 Jul 2017 09:02:08 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.60~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=17d52636898ea68aa0fc59232115f6b6d5a4b107;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: mm-numa-avoid-waiting-on-freed-migrated-pages.patch --- diff --git a/queue-3.18/mm-numa-avoid-waiting-on-freed-migrated-pages.patch b/queue-3.18/mm-numa-avoid-waiting-on-freed-migrated-pages.patch new file mode 100644 index 00000000000..cec788a264b --- /dev/null +++ b/queue-3.18/mm-numa-avoid-waiting-on-freed-migrated-pages.patch @@ -0,0 +1,90 @@ +From 3c226c637b69104f6b9f1c6ec5b08d7b741b3229 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Fri, 16 Jun 2017 14:02:34 -0700 +Subject: mm: numa: avoid waiting on freed migrated pages + +From: Mark Rutland + +commit 3c226c637b69104f6b9f1c6ec5b08d7b741b3229 upstream. + +In do_huge_pmd_numa_page(), we attempt to handle a migrating thp pmd by +waiting until the pmd is unlocked before we return and retry. However, +we can race with migrate_misplaced_transhuge_page(): + + // do_huge_pmd_numa_page // migrate_misplaced_transhuge_page() + // Holds 0 refs on page // Holds 2 refs on page + + vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); + /* ... */ + if (pmd_trans_migrating(*vmf->pmd)) { + page = pmd_page(*vmf->pmd); + spin_unlock(vmf->ptl); + ptl = pmd_lock(mm, pmd); + if (page_count(page) != 2)) { + /* roll back */ + } + /* ... */ + mlock_migrate_page(new_page, page); + /* ... */ + spin_unlock(ptl); + put_page(page); + put_page(page); // page freed here + wait_on_page_locked(page); + goto out; + } + +This can result in the freed page having its waiters flag set +unexpectedly, which trips the PAGE_FLAGS_CHECK_AT_PREP checks in the +page alloc/free functions. This has been observed on arm64 KVM guests. + +We can avoid this by having do_huge_pmd_numa_page() take a reference on +the page before dropping the pmd lock, mirroring what we do in +__migration_entry_wait(). + +When we hit the race, migrate_misplaced_transhuge_page() will see the +reference and abort the migration, as it may do today in other cases. + +Fixes: b8916634b77bffb2 ("mm: Prevent parallel splits during THP migration") +Link: http://lkml.kernel.org/r/1497349722-6731-2-git-send-email-will.deacon@arm.com +Signed-off-by: Mark Rutland +Signed-off-by: Will Deacon +Acked-by: Steve Capper +Acked-by: Kirill A. Shutemov +Acked-by: Vlastimil Babka +Cc: Mel Gorman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + + +--- + mm/huge_memory.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1294,8 +1294,12 @@ int do_huge_pmd_numa_page(struct mm_stru + * check_same as the page may no longer be mapped. + */ + if (unlikely(pmd_trans_migrating(*pmdp))) { ++ page = pmd_page(*pmdp); ++ if (!get_page_unless_zero(page)) ++ goto out_unlock; + spin_unlock(ptl); + wait_migrate_huge_page(vma->anon_vma, pmdp); ++ put_page(page); + goto out; + } + +@@ -1331,8 +1335,11 @@ int do_huge_pmd_numa_page(struct mm_stru + + /* Migration could have started since the pmd_trans_migrating check */ + if (!page_locked) { ++ if (!get_page_unless_zero(page)) ++ goto out_unlock; + spin_unlock(ptl); + wait_on_page_locked(page); ++ put_page(page); + page_nid = -1; + goto out; + } diff --git a/queue-3.18/series b/queue-3.18/series index e7ebc44bb61..6251b936cc6 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -20,3 +20,4 @@ alsa-hda-set-input_path-bitmap-to-zero-after-moving-it-to-new-place.patch drm-vmwgfx-free-hash-table-allocated-by-cmdbuf-managed-res-mgr.patch usb-gadget-f_fs-fix-possibe-deadlock.patch sysctl-enable-strict-writes.patch +mm-numa-avoid-waiting-on-freed-migrated-pages.patch