]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/huge_memory.c
Merge remote-tracking branch 'mfd-fixes/master'
[karo-tx-linux.git] / mm / huge_memory.c
index dbafffa5e2eeb3b0fdc65cce4f810398fa79de88..9c0b17295ba039da0b7e9cc1fb852822ba46172c 100644 (file)
@@ -882,6 +882,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1299,6 +1300,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
+       /*
+        * If there are potential migrations, wait for completion and retry
+        * without disrupting NUMA hinting information. Do not relock and
+        * check_same as the page may no longer be mapped.
+        */
+       if (unlikely(pmd_trans_migrating(*pmdp))) {
+               spin_unlock(ptl);
+               wait_migrate_huge_page(vma->anon_vma, pmdp);
+               goto out;
+       }
+
        page = pmd_page(pmd);
        BUG_ON(is_huge_zero_page(page));
        page_nid = page_to_nid(page);
@@ -1329,12 +1341,7 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        goto clear_pmdnuma;
        }
 
-       /*
-        * If there are potential migrations, wait for completion and retry. We
-        * do not relock and check_same as the page may no longer be mapped.
-        * Furtermore, even if the page is currently misplaced, there is no
-        * guarantee it is still misplaced after the migration completes.
-        */
+       /* Migration could have started since the pmd_trans_migrating check */
        if (!page_locked) {
                spin_unlock(ptl);
                wait_on_page_locked(page);
@@ -1532,6 +1539,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                ret = 1;
                if (!prot_numa) {
                        entry = pmdp_get_and_clear(mm, addr, pmd);
+                       if (pmd_numa(entry))
+                               entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
                        BUG_ON(pmd_write(entry));