|
@@ -1110,23 +1110,29 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
|
|
|
{
|
|
|
pte_t *pte;
|
|
|
spinlock_t *ptl;
|
|
|
+ int err = 0;
|
|
|
|
|
|
pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
|
|
|
if (!pte)
|
|
|
- return -ENOMEM;
|
|
|
+ return -EAGAIN;
|
|
|
arch_enter_lazy_mmu_mode();
|
|
|
do {
|
|
|
struct page *page = ZERO_PAGE(addr);
|
|
|
pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
|
|
|
+
|
|
|
+ if (unlikely(!pte_none(*pte))) {
|
|
|
+ err = -EEXIST;
|
|
|
+ pte++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
page_cache_get(page);
|
|
|
page_add_file_rmap(page);
|
|
|
inc_mm_counter(mm, file_rss);
|
|
|
- BUG_ON(!pte_none(*pte));
|
|
|
set_pte_at(mm, addr, pte, zero_pte);
|
|
|
} while (pte++, addr += PAGE_SIZE, addr != end);
|
|
|
arch_leave_lazy_mmu_mode();
|
|
|
pte_unmap_unlock(pte - 1, ptl);
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
|
|
@@ -1134,16 +1140,18 @@ static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
|
|
|
{
|
|
|
pmd_t *pmd;
|
|
|
unsigned long next;
|
|
|
+ int err;
|
|
|
|
|
|
pmd = pmd_alloc(mm, pud, addr);
|
|
|
if (!pmd)
|
|
|
- return -ENOMEM;
|
|
|
+ return -EAGAIN;
|
|
|
do {
|
|
|
next = pmd_addr_end(addr, end);
|
|
|
- if (zeromap_pte_range(mm, pmd, addr, next, prot))
|
|
|
- return -ENOMEM;
|
|
|
+ err = zeromap_pte_range(mm, pmd, addr, next, prot);
|
|
|
+ if (err)
|
|
|
+ break;
|
|
|
} while (pmd++, addr = next, addr != end);
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
|
|
@@ -1151,16 +1159,18 @@ static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
|
|
|
{
|
|
|
pud_t *pud;
|
|
|
unsigned long next;
|
|
|
+ int err;
|
|
|
|
|
|
pud = pud_alloc(mm, pgd, addr);
|
|
|
if (!pud)
|
|
|
- return -ENOMEM;
|
|
|
+ return -EAGAIN;
|
|
|
do {
|
|
|
next = pud_addr_end(addr, end);
|
|
|
- if (zeromap_pmd_range(mm, pud, addr, next, prot))
|
|
|
- return -ENOMEM;
|
|
|
+ err = zeromap_pmd_range(mm, pud, addr, next, prot);
|
|
|
+ if (err)
|
|
|
+ break;
|
|
|
} while (pud++, addr = next, addr != end);
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
int zeromap_page_range(struct vm_area_struct *vma,
|