diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/huge_memory.c | 40 | ||||
-rw-r--r-- | mm/memcontrol.c | 10 |
2 files changed, 32 insertions, 18 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e5b2d316be2e..471eb04066ff 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1376,9 +1376,10 @@ out: | |||
1376 | int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, | 1376 | int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, |
1377 | pmd_t *pmd, unsigned long addr) | 1377 | pmd_t *pmd, unsigned long addr) |
1378 | { | 1378 | { |
1379 | spinlock_t *ptl; | ||
1379 | int ret = 0; | 1380 | int ret = 0; |
1380 | 1381 | ||
1381 | if (__pmd_trans_huge_lock(pmd, vma) == 1) { | 1382 | if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
1382 | struct page *page; | 1383 | struct page *page; |
1383 | pgtable_t pgtable; | 1384 | pgtable_t pgtable; |
1384 | pmd_t orig_pmd; | 1385 | pmd_t orig_pmd; |
@@ -1393,7 +1394,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
1393 | pgtable = pgtable_trans_huge_withdraw(tlb->mm, pmd); | 1394 | pgtable = pgtable_trans_huge_withdraw(tlb->mm, pmd); |
1394 | if (is_huge_zero_pmd(orig_pmd)) { | 1395 | if (is_huge_zero_pmd(orig_pmd)) { |
1395 | atomic_long_dec(&tlb->mm->nr_ptes); | 1396 | atomic_long_dec(&tlb->mm->nr_ptes); |
1396 | spin_unlock(&tlb->mm->page_table_lock); | 1397 | spin_unlock(ptl); |
1397 | put_huge_zero_page(); | 1398 | put_huge_zero_page(); |
1398 | } else { | 1399 | } else { |
1399 | page = pmd_page(orig_pmd); | 1400 | page = pmd_page(orig_pmd); |
@@ -1402,7 +1403,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
1402 | add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); | 1403 | add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); |
1403 | VM_BUG_ON(!PageHead(page)); | 1404 | VM_BUG_ON(!PageHead(page)); |
1404 | atomic_long_dec(&tlb->mm->nr_ptes); | 1405 | atomic_long_dec(&tlb->mm->nr_ptes); |
1405 | spin_unlock(&tlb->mm->page_table_lock); | 1406 | spin_unlock(ptl); |
1406 | tlb_remove_page(tlb, page); | 1407 | tlb_remove_page(tlb, page); |
1407 | } | 1408 | } |
1408 | pte_free(tlb->mm, pgtable); | 1409 | pte_free(tlb->mm, pgtable); |
@@ -1415,14 +1416,15 @@ int mincore_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1415 | unsigned long addr, unsigned long end, | 1416 | unsigned long addr, unsigned long end, |
1416 | unsigned char *vec) | 1417 | unsigned char *vec) |
1417 | { | 1418 | { |
1419 | spinlock_t *ptl; | ||
1418 | int ret = 0; | 1420 | int ret = 0; |
1419 | 1421 | ||
1420 | if (__pmd_trans_huge_lock(pmd, vma) == 1) { | 1422 | if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
1421 | /* | 1423 | /* |
1422 | * All logical pages in the range are present | 1424 | * All logical pages in the range are present |
1423 | * if backed by a huge page. | 1425 | * if backed by a huge page. |
1424 | */ | 1426 | */ |
1425 | spin_unlock(&vma->vm_mm->page_table_lock); | 1427 | spin_unlock(ptl); |
1426 | memset(vec, 1, (end - addr) >> PAGE_SHIFT); | 1428 | memset(vec, 1, (end - addr) >> PAGE_SHIFT); |
1427 | ret = 1; | 1429 | ret = 1; |
1428 | } | 1430 | } |
@@ -1435,6 +1437,7 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma, | |||
1435 | unsigned long new_addr, unsigned long old_end, | 1437 | unsigned long new_addr, unsigned long old_end, |
1436 | pmd_t *old_pmd, pmd_t *new_pmd) | 1438 | pmd_t *old_pmd, pmd_t *new_pmd) |
1437 | { | 1439 | { |
1440 | spinlock_t *old_ptl, *new_ptl; | ||
1438 | int ret = 0; | 1441 | int ret = 0; |
1439 | pmd_t pmd; | 1442 | pmd_t pmd; |
1440 | 1443 | ||
@@ -1455,12 +1458,21 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma, | |||
1455 | goto out; | 1458 | goto out; |
1456 | } | 1459 | } |
1457 | 1460 | ||
1458 | ret = __pmd_trans_huge_lock(old_pmd, vma); | 1461 | /* |
1462 | * We don't have to worry about the ordering of src and dst | ||
1463 | * ptlocks because exclusive mmap_sem prevents deadlock. | ||
1464 | */ | ||
1465 | ret = __pmd_trans_huge_lock(old_pmd, vma, &old_ptl); | ||
1459 | if (ret == 1) { | 1466 | if (ret == 1) { |
1467 | new_ptl = pmd_lockptr(mm, new_pmd); | ||
1468 | if (new_ptl != old_ptl) | ||
1469 | spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); | ||
1460 | pmd = pmdp_get_and_clear(mm, old_addr, old_pmd); | 1470 | pmd = pmdp_get_and_clear(mm, old_addr, old_pmd); |
1461 | VM_BUG_ON(!pmd_none(*new_pmd)); | 1471 | VM_BUG_ON(!pmd_none(*new_pmd)); |
1462 | set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd)); | 1472 | set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd)); |
1463 | spin_unlock(&mm->page_table_lock); | 1473 | if (new_ptl != old_ptl) |
1474 | spin_unlock(new_ptl); | ||
1475 | spin_unlock(old_ptl); | ||
1464 | } | 1476 | } |
1465 | out: | 1477 | out: |
1466 | return ret; | 1478 | return ret; |
@@ -1476,9 +1488,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1476 | unsigned long addr, pgprot_t newprot, int prot_numa) | 1488 | unsigned long addr, pgprot_t newprot, int prot_numa) |
1477 | { | 1489 | { |
1478 | struct mm_struct *mm = vma->vm_mm; | 1490 | struct mm_struct *mm = vma->vm_mm; |
1491 | spinlock_t *ptl; | ||
1479 | int ret = 0; | 1492 | int ret = 0; |
1480 | 1493 | ||
1481 | if (__pmd_trans_huge_lock(pmd, vma) == 1) { | 1494 | if (__pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
1482 | pmd_t entry; | 1495 | pmd_t entry; |
1483 | ret = 1; | 1496 | ret = 1; |
1484 | if (!prot_numa) { | 1497 | if (!prot_numa) { |
@@ -1507,7 +1520,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1507 | if (ret == HPAGE_PMD_NR) | 1520 | if (ret == HPAGE_PMD_NR) |
1508 | set_pmd_at(mm, addr, pmd, entry); | 1521 | set_pmd_at(mm, addr, pmd, entry); |
1509 | 1522 | ||
1510 | spin_unlock(&vma->vm_mm->page_table_lock); | 1523 | spin_unlock(ptl); |
1511 | } | 1524 | } |
1512 | 1525 | ||
1513 | return ret; | 1526 | return ret; |
@@ -1520,12 +1533,13 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1520 | * Note that if it returns 1, this routine returns without unlocking page | 1533 | * Note that if it returns 1, this routine returns without unlocking page |
1521 | * table locks. So callers must unlock them. | 1534 | * table locks. So callers must unlock them. |
1522 | */ | 1535 | */ |
1523 | int __pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma) | 1536 | int __pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma, |
1537 | spinlock_t **ptl) | ||
1524 | { | 1538 | { |
1525 | spin_lock(&vma->vm_mm->page_table_lock); | 1539 | *ptl = pmd_lock(vma->vm_mm, pmd); |
1526 | if (likely(pmd_trans_huge(*pmd))) { | 1540 | if (likely(pmd_trans_huge(*pmd))) { |
1527 | if (unlikely(pmd_trans_splitting(*pmd))) { | 1541 | if (unlikely(pmd_trans_splitting(*pmd))) { |
1528 | spin_unlock(&vma->vm_mm->page_table_lock); | 1542 | spin_unlock(*ptl); |
1529 | wait_split_huge_page(vma->anon_vma, pmd); | 1543 | wait_split_huge_page(vma->anon_vma, pmd); |
1530 | return -1; | 1544 | return -1; |
1531 | } else { | 1545 | } else { |
@@ -1534,7 +1548,7 @@ int __pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma) | |||
1534 | return 1; | 1548 | return 1; |
1535 | } | 1549 | } |
1536 | } | 1550 | } |
1537 | spin_unlock(&vma->vm_mm->page_table_lock); | 1551 | spin_unlock(*ptl); |
1538 | return 0; | 1552 | return 0; |
1539 | } | 1553 | } |
1540 | 1554 | ||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e3cd40b2d5d9..f1a0ae6e11b8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -6605,10 +6605,10 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, | |||
6605 | pte_t *pte; | 6605 | pte_t *pte; |
6606 | spinlock_t *ptl; | 6606 | spinlock_t *ptl; |
6607 | 6607 | ||
6608 | if (pmd_trans_huge_lock(pmd, vma) == 1) { | 6608 | if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
6609 | if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE) | 6609 | if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE) |
6610 | mc.precharge += HPAGE_PMD_NR; | 6610 | mc.precharge += HPAGE_PMD_NR; |
6611 | spin_unlock(&vma->vm_mm->page_table_lock); | 6611 | spin_unlock(ptl); |
6612 | return 0; | 6612 | return 0; |
6613 | } | 6613 | } |
6614 | 6614 | ||
@@ -6797,9 +6797,9 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, | |||
6797 | * to be unlocked in __split_huge_page_splitting(), where the main | 6797 | * to be unlocked in __split_huge_page_splitting(), where the main |
6798 | * part of thp split is not executed yet. | 6798 | * part of thp split is not executed yet. |
6799 | */ | 6799 | */ |
6800 | if (pmd_trans_huge_lock(pmd, vma) == 1) { | 6800 | if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
6801 | if (mc.precharge < HPAGE_PMD_NR) { | 6801 | if (mc.precharge < HPAGE_PMD_NR) { |
6802 | spin_unlock(&vma->vm_mm->page_table_lock); | 6802 | spin_unlock(ptl); |
6803 | return 0; | 6803 | return 0; |
6804 | } | 6804 | } |
6805 | target_type = get_mctgt_type_thp(vma, addr, *pmd, &target); | 6805 | target_type = get_mctgt_type_thp(vma, addr, *pmd, &target); |
@@ -6816,7 +6816,7 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, | |||
6816 | } | 6816 | } |
6817 | put_page(page); | 6817 | put_page(page); |
6818 | } | 6818 | } |
6819 | spin_unlock(&vma->vm_mm->page_table_lock); | 6819 | spin_unlock(ptl); |
6820 | return 0; | 6820 | return 0; |
6821 | } | 6821 | } |
6822 | 6822 | ||