X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=mm%2Fmremap.c;h=1b0b71c2a51bb1476c88aa3d084add34c0f59313;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=0740146dcb220a3602270c642aad3f0df680ca1a;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/mm/mremap.c b/mm/mremap.c index 0740146dc..1b0b71c2a 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -32,26 +31,16 @@ static pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr) pte_t *pte = NULL; pgd = pgd_offset(mm, addr); - if (pgd_none(*pgd)) + if (pgd_none_or_clear_bad(pgd)) goto end; pud = pud_offset(pgd, addr); - if (pud_none(*pud)) + if (pud_none_or_clear_bad(pud)) goto end; - if (pud_bad(*pud)) { - pud_ERROR(*pud); - pud_clear(pud); - goto end; - } pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) - goto end; - if (pmd_bad(*pmd)) { - pmd_ERROR(*pmd); - pmd_clear(pmd); + if (pmd_none_or_clear_bad(pmd)) goto end; - } pte = pte_offset_map_nested(pmd, addr); if (pte_none(*pte)) { @@ -69,15 +58,17 @@ static pte_t *get_one_pte_map(struct mm_struct *mm, unsigned long addr) pmd_t *pmd; pgd = pgd_offset(mm, addr); - if (pgd_none(*pgd)) + if (pgd_none_or_clear_bad(pgd)) return NULL; pud = pud_offset(pgd, addr); - if (pud_none(*pud)) + if (pud_none_or_clear_bad(pud)) return NULL; + pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) + if (pmd_none_or_clear_bad(pmd)) return NULL; + return pte_offset_map(pmd, addr); } @@ -151,7 +142,7 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr, if (dst) { pte_t pte; pte = ptep_clear_flush(vma, old_addr, src); - set_pte(dst, pte); + set_pte_at(mm, new_addr, dst, pte); } else error = -ENOMEM; pte_unmap_nested(src); @@ -234,6 +225,12 @@ static unsigned long move_vma(struct vm_area_struct *vma, split = 1; } + /* + * if we failed to move page tables we still do total_vm increment + * since do_munmap() will decrement it by old_len == new_len + */ + vx_vmpages_add(mm, new_len >> PAGE_SHIFT); + if (do_munmap(mm, old_addr, old_len) < 0) { /* OOM: unable to split vma, just get accounts right */ vm_unacct_memory(excess >> PAGE_SHIFT); @@ -247,20 +244,14 @@ static unsigned long move_vma(struct vm_area_struct *vma, vma->vm_next->vm_flags |= VM_ACCOUNT; } - // mm->total_vm += new_len >> PAGE_SHIFT; - vx_vmpages_add(mm, new_len >> PAGE_SHIFT); __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT); if (vm_flags & VM_LOCKED) { - // mm->locked_vm += new_len >> PAGE_SHIFT; vx_vmlocked_add(mm, new_len >> PAGE_SHIFT); if (new_len > old_len) make_pages_present(new_addr + old_len, new_addr + new_len); } - acct_update_integrals(); - update_mem_hiwater(); - return new_addr; } @@ -361,18 +352,14 @@ unsigned long do_mremap(unsigned long addr, ret = -EAGAIN; if (locked > lock_limit && !capable(CAP_IPC_LOCK)) goto out; - ret = -ENOMEM; if (!vx_vmlocked_avail(current->mm, (new_len - old_len) >> PAGE_SHIFT)) goto out; } - ret = -ENOMEM; - if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len) - > current->signal->rlim[RLIMIT_AS].rlim_cur) - goto out; - /* check context space, maybe only Private writable mapping? */ - if (!vx_vmpages_avail(current->mm, (new_len - old_len) >> PAGE_SHIFT)) + if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) { + ret = -ENOMEM; goto out; + } if (vma->vm_flags & VM_ACCOUNT) { charged = (new_len - old_len) >> PAGE_SHIFT; @@ -396,18 +383,14 @@ unsigned long do_mremap(unsigned long addr, vma_adjust(vma, vma->vm_start, addr + new_len, vma->vm_pgoff, NULL); - // current->mm->total_vm += pages; vx_vmpages_add(current->mm, pages); __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, pages); if (vma->vm_flags & VM_LOCKED) { - // current->mm->locked_vm += pages; vx_vmlocked_add(vma->vm_mm, pages); make_pages_present(addr + old_len, addr + new_len); } - acct_update_integrals(); - update_mem_hiwater(); ret = addr; goto out; }