[PATCH 20 of 25] add page_check_address_pmd to find the pmd mapping a transparent hugepage

Andrea Arcangeli
2009-11-14T18:10:25Z

page_check_address_pmd is used to find the pmds that might be mapping the
hugepage through the anon_vma in order to freeze and unfreeze them.

Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
---

diff --git a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -55,8 +55,10 @@
#include <linux/memcontrol.h>
#include <linux/mmu_notifier.h>
#include <linux/migrate.h>
+#include <linux/hugetlb.h>

#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>

#include "internal.h"

@@ -260,6 +262,42 @@ unsigned long page_address_in_vma(struct
return vma_address(page, vma);
}

+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static pmd_t *__page_check_address_pmd(struct page *page, struct mm_struct *mm,
+ unsigned long address, int notfrozen)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd, *ret = NULL;
+
+ pgd = pgd_offset(mm, address);
+ if (!pgd_present(*pgd))
+ goto out;
+
+ pud = pud_offset(pgd, address);
+ if (!pud_present(*pud))
+ goto out;
+
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd))
+ goto out;
+ VM_BUG_ON(notfrozen == 1 && pmd_trans_frozen(*pmd));
+ if (pmd_trans_huge(*pmd) && pmd_pgtable(*pmd) == page) {
+ VM_BUG_ON(notfrozen == -1 && !pmd_trans_frozen(*pmd));
+ ret = pmd;
+ }
+out:
+ return ret;
+}
+
+#define page_check_address_pmd(__page, __mm, __address) \
+ __page_check_address_pmd(__page, __mm, __address, 0)
+#define page_check_address_pmd_notfrozen(__page, __mm, __address) \
+ __page_check_address_pmd(__page, __mm, __address, 1)
+#define page_check_address_pmd_frozen(__page, __mm, __address) \
+ __page_check_address_pmd(__page, __mm, __address, -1)
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
/*
* Check that @page is mapped at @address into @mm.
*