From: Greg Kroah-Hartman Date: Mon, 3 Jul 2017 09:02:28 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.18.60~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ba66a07e0240162efb0a549c6a3ee77f3d014a14;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: mm-numa-avoid-waiting-on-freed-migrated-pages.patch --- diff --git a/queue-4.4/mm-numa-avoid-waiting-on-freed-migrated-pages.patch b/queue-4.4/mm-numa-avoid-waiting-on-freed-migrated-pages.patch new file mode 100644 index 00000000000..8a5288b9979 --- /dev/null +++ b/queue-4.4/mm-numa-avoid-waiting-on-freed-migrated-pages.patch @@ -0,0 +1,89 @@ +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 | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1363,8 +1363,11 @@ int do_huge_pmd_numa_page(struct mm_stru + */ + if (unlikely(pmd_trans_migrating(*pmdp))) { + page = pmd_page(*pmdp); ++ if (!get_page_unless_zero(page)) ++ goto out_unlock; + spin_unlock(ptl); + wait_on_page_locked(page); ++ put_page(page); + goto out; + } + +@@ -1396,8 +1399,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-4.4/series b/queue-4.4/series index b8674a2f1c5..6237ab75072 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -28,3 +28,4 @@ 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 block-fix-module-reference-leak-on-put_disk-call-for-cgroups-throttle.patch +mm-numa-avoid-waiting-on-freed-migrated-pages.patch