|
@@ -1295,13 +1295,14 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
|
if (current_nid == numa_node_id())
|
|
|
count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
|
|
|
|
|
|
- target_nid = mpol_misplaced(page, vma, haddr);
|
|
|
- if (target_nid == -1) {
|
|
|
- put_page(page);
|
|
|
- goto clear_pmdnuma;
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * Acquire the page lock to serialise THP migrations but avoid dropping
|
|
|
+ * page_table_lock if at all possible
|
|
|
+ */
|
|
|
+ if (trylock_page(page))
|
|
|
+ goto got_lock;
|
|
|
|
|
|
- /* Acquire the page lock to serialise THP migrations */
|
|
|
+ /* Serialise against migrationa and check placement check placement */
|
|
|
spin_unlock(&mm->page_table_lock);
|
|
|
lock_page(page);
|
|
|
|
|
@@ -1312,9 +1313,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
|
put_page(page);
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
- spin_unlock(&mm->page_table_lock);
|
|
|
+
|
|
|
+got_lock:
|
|
|
+ target_nid = mpol_misplaced(page, vma, haddr);
|
|
|
+ if (target_nid == -1) {
|
|
|
+ unlock_page(page);
|
|
|
+ put_page(page);
|
|
|
+ goto clear_pmdnuma;
|
|
|
+ }
|
|
|
|
|
|
/* Migrate the THP to the requested node */
|
|
|
+ spin_unlock(&mm->page_table_lock);
|
|
|
migrated = migrate_misplaced_transhuge_page(mm, vma,
|
|
|
pmdp, pmd, addr, page, target_nid);
|
|
|
if (!migrated)
|