selinux: de-crapify avc cache stat code generation
[pandora-kernel.git] / mm / pagewalk.c
index 7cfa6ae..c3450d5 100644 (file)
@@ -33,19 +33,35 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 
        pmd = pmd_offset(pud, addr);
        do {
+again:
                next = pmd_addr_end(addr, end);
-               split_huge_page_pmd(walk->mm, pmd);
-               if (pmd_none_or_clear_bad(pmd)) {
+               if (pmd_none(*pmd)) {
                        if (walk->pte_hole)
                                err = walk->pte_hole(addr, next, walk);
                        if (err)
                                break;
                        continue;
                }
+               /*
+                * This implies that each ->pmd_entry() handler
+                * needs to know about pmd_trans_huge() pmds
+                */
                if (walk->pmd_entry)
                        err = walk->pmd_entry(pmd, addr, next, walk);
-               if (!err && walk->pte_entry)
-                       err = walk_pte_range(pmd, addr, next, walk);
+               if (err)
+                       break;
+
+               /*
+                * Check this here so we only break down trans_huge
+                * pages when we _need_ to
+                */
+               if (!walk->pte_entry)
+                       continue;
+
+               split_huge_page_pmd(walk->mm, pmd);
+               if (pmd_none_or_clear_bad(pmd))
+                       goto again;
+               err = walk_pte_range(pmd, addr, next, walk);
                if (err)
                        break;
        } while (pmd++, addr = next, addr != end);