aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/huge_memory.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0ad946974df4..64f8aadb0595 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1288,18 +1288,18 @@ out:
1288int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, 1288int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
1289 unsigned long addr, pmd_t pmd, pmd_t *pmdp) 1289 unsigned long addr, pmd_t pmd, pmd_t *pmdp)
1290{ 1290{
1291 struct anon_vma *anon_vma = NULL;
1291 struct page *page; 1292 struct page *page;
1292 unsigned long haddr = addr & HPAGE_PMD_MASK; 1293 unsigned long haddr = addr & HPAGE_PMD_MASK;
1293 int target_nid; 1294 int target_nid;
1294 int current_nid = -1; 1295 int current_nid = -1;
1295 bool migrated; 1296 bool migrated, page_locked;
1296 1297
1297 spin_lock(&mm->page_table_lock); 1298 spin_lock(&mm->page_table_lock);
1298 if (unlikely(!pmd_same(pmd, *pmdp))) 1299 if (unlikely(!pmd_same(pmd, *pmdp)))
1299 goto out_unlock; 1300 goto out_unlock;
1300 1301
1301 page = pmd_page(pmd); 1302 page = pmd_page(pmd);
1302 get_page(page);
1303 current_nid = page_to_nid(page); 1303 current_nid = page_to_nid(page);
1304 count_vm_numa_event(NUMA_HINT_FAULTS); 1304 count_vm_numa_event(NUMA_HINT_FAULTS);
1305 if (current_nid == numa_node_id()) 1305 if (current_nid == numa_node_id())
@@ -1309,12 +1309,29 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
1309 * Acquire the page lock to serialise THP migrations but avoid dropping 1309 * Acquire the page lock to serialise THP migrations but avoid dropping
1310 * page_table_lock if at all possible 1310 * page_table_lock if at all possible
1311 */ 1311 */
1312 if (trylock_page(page)) 1312 page_locked = trylock_page(page);
1313 goto got_lock; 1313 target_nid = mpol_misplaced(page, vma, haddr);
1314 if (target_nid == -1) {
1315 /* If the page was locked, there are no parallel migrations */
1316 if (page_locked) {
1317 unlock_page(page);
1318 goto clear_pmdnuma;
1319 }
1314 1320
1315 /* Serialise against migrationa and check placement check placement */ 1321 /* Otherwise wait for potential migrations and retry fault */
1322 spin_unlock(&mm->page_table_lock);
1323 wait_on_page_locked(page);
1324 goto out;
1325 }
1326
1327 /* Page is misplaced, serialise migrations and parallel THP splits */
1328 get_page(page);
1316 spin_unlock(&mm->page_table_lock); 1329 spin_unlock(&mm->page_table_lock);
1317 lock_page(page); 1330 if (!page_locked) {
1331 lock_page(page);
1332 page_locked = true;
1333 }
1334 anon_vma = page_lock_anon_vma_read(page);
1318 1335
1319 /* Confirm the PTE did not while locked */ 1336 /* Confirm the PTE did not while locked */
1320 spin_lock(&mm->page_table_lock); 1337 spin_lock(&mm->page_table_lock);
@@ -1324,14 +1341,6 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
1324 goto out_unlock; 1341 goto out_unlock;
1325 } 1342 }
1326 1343
1327got_lock:
1328 target_nid = mpol_misplaced(page, vma, haddr);
1329 if (target_nid == -1) {
1330 unlock_page(page);
1331 put_page(page);
1332 goto clear_pmdnuma;
1333 }
1334
1335 /* Migrate the THP to the requested node */ 1344 /* Migrate the THP to the requested node */
1336 spin_unlock(&mm->page_table_lock); 1345 spin_unlock(&mm->page_table_lock);
1337 migrated = migrate_misplaced_transhuge_page(mm, vma, 1346 migrated = migrate_misplaced_transhuge_page(mm, vma,
@@ -1340,6 +1349,8 @@ got_lock:
1340 goto check_same; 1349 goto check_same;
1341 1350
1342 task_numa_fault(target_nid, HPAGE_PMD_NR, true); 1351 task_numa_fault(target_nid, HPAGE_PMD_NR, true);
1352 if (anon_vma)
1353 page_unlock_anon_vma_read(anon_vma);
1343 return 0; 1354 return 0;
1344 1355
1345check_same: 1356check_same:
@@ -1356,6 +1367,11 @@ clear_pmdnuma:
1356 update_mmu_cache_pmd(vma, addr, pmdp); 1367 update_mmu_cache_pmd(vma, addr, pmdp);
1357out_unlock: 1368out_unlock:
1358 spin_unlock(&mm->page_table_lock); 1369 spin_unlock(&mm->page_table_lock);
1370
1371out:
1372 if (anon_vma)
1373 page_unlock_anon_vma_read(anon_vma);
1374
1359 if (current_nid != -1) 1375 if (current_nid != -1)
1360 task_numa_fault(current_nid, HPAGE_PMD_NR, false); 1376 task_numa_fault(current_nid, HPAGE_PMD_NR, false);
1361 return 0; 1377 return 0;