diff options
Diffstat (limited to 'fs/proc/task_mmu.c')
-rw-r--r-- | fs/proc/task_mmu.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 229cb546bee0..541583510cfb 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -1518,6 +1518,32 @@ static struct page *can_gather_numa_stats(pte_t pte, struct vm_area_struct *vma, | |||
1518 | return page; | 1518 | return page; |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
1522 | static struct page *can_gather_numa_stats_pmd(pmd_t pmd, | ||
1523 | struct vm_area_struct *vma, | ||
1524 | unsigned long addr) | ||
1525 | { | ||
1526 | struct page *page; | ||
1527 | int nid; | ||
1528 | |||
1529 | if (!pmd_present(pmd)) | ||
1530 | return NULL; | ||
1531 | |||
1532 | page = vm_normal_page_pmd(vma, addr, pmd); | ||
1533 | if (!page) | ||
1534 | return NULL; | ||
1535 | |||
1536 | if (PageReserved(page)) | ||
1537 | return NULL; | ||
1538 | |||
1539 | nid = page_to_nid(page); | ||
1540 | if (!node_isset(nid, node_states[N_MEMORY])) | ||
1541 | return NULL; | ||
1542 | |||
1543 | return page; | ||
1544 | } | ||
1545 | #endif | ||
1546 | |||
1521 | static int gather_pte_stats(pmd_t *pmd, unsigned long addr, | 1547 | static int gather_pte_stats(pmd_t *pmd, unsigned long addr, |
1522 | unsigned long end, struct mm_walk *walk) | 1548 | unsigned long end, struct mm_walk *walk) |
1523 | { | 1549 | { |
@@ -1527,14 +1553,14 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, | |||
1527 | pte_t *orig_pte; | 1553 | pte_t *orig_pte; |
1528 | pte_t *pte; | 1554 | pte_t *pte; |
1529 | 1555 | ||
1556 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
1530 | ptl = pmd_trans_huge_lock(pmd, vma); | 1557 | ptl = pmd_trans_huge_lock(pmd, vma); |
1531 | if (ptl) { | 1558 | if (ptl) { |
1532 | pte_t huge_pte = *(pte_t *)pmd; | ||
1533 | struct page *page; | 1559 | struct page *page; |
1534 | 1560 | ||
1535 | page = can_gather_numa_stats(huge_pte, vma, addr); | 1561 | page = can_gather_numa_stats_pmd(*pmd, vma, addr); |
1536 | if (page) | 1562 | if (page) |
1537 | gather_stats(page, md, pte_dirty(huge_pte), | 1563 | gather_stats(page, md, pmd_dirty(*pmd), |
1538 | HPAGE_PMD_SIZE/PAGE_SIZE); | 1564 | HPAGE_PMD_SIZE/PAGE_SIZE); |
1539 | spin_unlock(ptl); | 1565 | spin_unlock(ptl); |
1540 | return 0; | 1566 | return 0; |
@@ -1542,6 +1568,7 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, | |||
1542 | 1568 | ||
1543 | if (pmd_trans_unstable(pmd)) | 1569 | if (pmd_trans_unstable(pmd)) |
1544 | return 0; | 1570 | return 0; |
1571 | #endif | ||
1545 | orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); | 1572 | orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); |
1546 | do { | 1573 | do { |
1547 | struct page *page = can_gather_numa_stats(*pte, vma, addr); | 1574 | struct page *page = can_gather_numa_stats(*pte, vma, addr); |