Merge tag 'v4.0-rc1' into x86/mm, to refresh the tree
[linux-2.6-block.git] / arch / x86 / mm / pgtable.c
index d223e1fe1dd2b47173c9b9a675cc856b7fe0cd70..5a7e5252c878bdcd2e45a11257adc15763cdea5f 100644 (file)
@@ -190,7 +190,7 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
 
 #endif /* CONFIG_X86_PAE */
 
-static void free_pmds(pmd_t *pmds[])
+static void free_pmds(struct mm_struct *mm, pmd_t *pmds[])
 {
        int i;
 
@@ -198,10 +198,11 @@ static void free_pmds(pmd_t *pmds[])
                if (pmds[i]) {
                        pgtable_pmd_page_dtor(virt_to_page(pmds[i]));
                        free_page((unsigned long)pmds[i]);
+                       mm_dec_nr_pmds(mm);
                }
 }
 
-static int preallocate_pmds(pmd_t *pmds[])
+static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[])
 {
        int i;
        bool failed = false;
@@ -215,11 +216,13 @@ static int preallocate_pmds(pmd_t *pmds[])
                        pmd = NULL;
                        failed = true;
                }
+               if (pmd)
+                       mm_inc_nr_pmds(mm);
                pmds[i] = pmd;
        }
 
        if (failed) {
-               free_pmds(pmds);
+               free_pmds(mm, pmds);
                return -ENOMEM;
        }
 
@@ -246,6 +249,7 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
 
                        paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
                        pmd_free(mm, pmd);
+                       mm_dec_nr_pmds(mm);
                }
        }
 }
@@ -358,7 +362,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 
        mm->pgd = pgd;
 
-       if (preallocate_pmds(pmds) != 0)
+       if (preallocate_pmds(mm, pmds) != 0)
                goto out_free_pgd;
 
        if (paravirt_pgd_alloc(mm) != 0)
@@ -379,7 +383,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
        return pgd;
 
 out_free_pmds:
-       free_pmds(pmds);
+       free_pmds(mm, pmds);
 out_free_pgd:
        _pgd_free(pgd);
 out: