unsigned long next;
        long pages = 0;
        unsigned long nr_huge_updates = 0;
-       struct mmu_notifier_range range;
-
-       range.start = 0;
 
        pmd = pmd_offset(pud, addr);
        do {
                if (pmd_none(*pmd))
                        goto next;
 
-               /* invoke the mmu notifier if the pmd is populated */
-               if (!range.start) {
-                       mmu_notifier_range_init(&range,
-                               MMU_NOTIFY_PROTECTION_VMA, 0,
-                               vma->vm_mm, addr, end);
-                       mmu_notifier_invalidate_range_start(&range);
-               }
-
                _pmd = pmdp_get_lockless(pmd);
                if (is_swap_pmd(_pmd) || pmd_trans_huge(_pmd) || pmd_devmap(_pmd)) {
                        if ((next - addr != HPAGE_PMD_SIZE) ||
                cond_resched();
        } while (pmd++, addr = next, addr != end);
 
-       if (range.start)
-               mmu_notifier_invalidate_range_end(&range);
-
        if (nr_huge_updates)
                count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates);
        return pages;
                struct vm_area_struct *vma, p4d_t *p4d, unsigned long addr,
                unsigned long end, pgprot_t newprot, unsigned long cp_flags)
 {
+       struct mmu_notifier_range range;
        pud_t *pud;
        unsigned long next;
        long pages = 0, ret;
 
+       range.start = 0;
+
        pud = pud_offset(p4d, addr);
        do {
                next = pud_addr_end(addr, end);
                ret = change_prepare(vma, pud, pmd, addr, cp_flags);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       pages = ret;
+                       break;
+               }
                if (pud_none_or_clear_bad(pud))
                        continue;
+               if (!range.start) {
+                       mmu_notifier_range_init(&range,
+                                               MMU_NOTIFY_PROTECTION_VMA, 0,
+                                               vma->vm_mm, addr, end);
+                       mmu_notifier_invalidate_range_start(&range);
+               }
                pages += change_pmd_range(tlb, vma, pud, addr, next, newprot,
                                          cp_flags);
        } while (pud++, addr = next, addr != end);
 
+       if (range.start)
+               mmu_notifier_invalidate_range_end(&range);
+
        return pages;
 }