net/mlx4_core: Initialize all mailbox buffers to zero before use
[cascardo/linux.git] / mm / huge_memory.c
index d8534b3..cca80d9 100644 (file)
@@ -1281,18 +1281,19 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        struct anon_vma *anon_vma = NULL;
        struct page *page;
        unsigned long haddr = addr & HPAGE_PMD_MASK;
+       int page_nid = -1, this_nid = numa_node_id();
        int target_nid;
-       int current_nid = -1;
-       bool migrated, page_locked;
+       bool page_locked;
+       bool migrated = false;
 
        spin_lock(&mm->page_table_lock);
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
        page = pmd_page(pmd);
-       current_nid = page_to_nid(page);
+       page_nid = page_to_nid(page);
        count_vm_numa_event(NUMA_HINT_FAULTS);
-       if (current_nid == numa_node_id())
+       if (page_nid == this_nid)
                count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
 
        /*
@@ -1303,24 +1304,25 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        target_nid = mpol_misplaced(page, vma, haddr);
        if (target_nid == -1) {
                /* If the page was locked, there are no parallel migrations */
-               if (page_locked) {
-                       unlock_page(page);
+               if (page_locked)
                        goto clear_pmdnuma;
-               }
 
-               /* Otherwise wait for potential migrations and retry fault */
+               /*
+                * Otherwise wait for potential migrations and retry. We do
+                * relock and check_same as the page may no longer be mapped.
+                * As the fault is being retried, do not account for it.
+                */
                spin_unlock(&mm->page_table_lock);
                wait_on_page_locked(page);
+               page_nid = -1;
                goto out;
        }
 
        /* Page is misplaced, serialise migrations and parallel THP splits */
        get_page(page);
        spin_unlock(&mm->page_table_lock);
-       if (!page_locked) {
+       if (!page_locked)
                lock_page(page);
-               page_locked = true;
-       }
        anon_vma = page_lock_anon_vma_read(page);
 
        /* Confirm the PTE did not while locked */
@@ -1328,33 +1330,28 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp))) {
                unlock_page(page);
                put_page(page);
+               page_nid = -1;
                goto out_unlock;
        }
 
-       /* Migrate the THP to the requested node */
+       /*
+        * Migrate the THP to the requested node, returns with page unlocked
+        * and pmd_numa cleared.
+        */
        spin_unlock(&mm->page_table_lock);
        migrated = migrate_misplaced_transhuge_page(mm, vma,
                                pmdp, pmd, addr, page, target_nid);
-       if (!migrated)
-               goto check_same;
-
-       task_numa_fault(target_nid, HPAGE_PMD_NR, true);
-       if (anon_vma)
-               page_unlock_anon_vma_read(anon_vma);
-       return 0;
+       if (migrated)
+               page_nid = target_nid;
 
-check_same:
-       spin_lock(&mm->page_table_lock);
-       if (unlikely(!pmd_same(pmd, *pmdp))) {
-               /* Someone else took our fault */
-               current_nid = -1;
-               goto out_unlock;
-       }
+       goto out;
 clear_pmdnuma:
+       BUG_ON(!PageLocked(page));
        pmd = pmd_mknonnuma(pmd);
        set_pmd_at(mm, haddr, pmdp, pmd);
        VM_BUG_ON(pmd_numa(*pmdp));
        update_mmu_cache_pmd(vma, addr, pmdp);
+       unlock_page(page);
 out_unlock:
        spin_unlock(&mm->page_table_lock);
 
@@ -1362,8 +1359,9 @@ out:
        if (anon_vma)
                page_unlock_anon_vma_read(anon_vma);
 
-       if (current_nid != -1)
-               task_numa_fault(current_nid, HPAGE_PMD_NR, false);
+       if (page_nid != -1)
+               task_numa_fault(page_nid, HPAGE_PMD_NR, migrated);
+
        return 0;
 }