From: Hugh Dickins Sometimes /proc//status shows VmLib: 42949..... kB. mprotect_fixup must note oldflags on entry: if vma_merge is successful, vma->vm_flags afterwards may be either the oldflags or the newflags, and the extent of the change will be less than the extent of the vma. And let's use unsigned long for these flags throughout. Signed-off-by: Hugh Dickins Acked-by: William Lee Irwin III Signed-off-by: Andrew Morton --- 25-akpm/mm/mprotect.c | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff -puN mm/mprotect.c~vmlib-wrapped-mprotect-flags mm/mprotect.c --- 25/mm/mprotect.c~vmlib-wrapped-mprotect-flags Thu Dec 9 13:07:13 2004 +++ 25-akpm/mm/mprotect.c Thu Dec 9 13:07:13 2004 @@ -111,15 +111,17 @@ change_protection(struct vm_area_struct static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - unsigned long start, unsigned long end, unsigned int newflags) + unsigned long start, unsigned long end, unsigned long newflags) { struct mm_struct * mm = vma->vm_mm; + unsigned long oldflags = vma->vm_flags; + long nrpages = (end - start) >> PAGE_SHIFT; unsigned long charged = 0; pgprot_t newprot; pgoff_t pgoff; int error; - if (newflags == vma->vm_flags) { + if (newflags == oldflags) { *pprev = vma; return 0; } @@ -133,8 +135,8 @@ mprotect_fixup(struct vm_area_struct *vm * a MAP_NORESERVE private mapping to writable will now reserve. */ if (newflags & VM_WRITE) { - if (!(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { - charged = (end - start) >> PAGE_SHIFT; + if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { + charged = nrpages; if (security_vm_enough_memory(charged)) return -ENOMEM; newflags |= VM_ACCOUNT; @@ -176,11 +178,11 @@ success: * vm_flags and vm_page_prot are protected by the mmap_sem * held in write mode. */ - vm_stat_unaccount(vma); vma->vm_flags = newflags; vma->vm_page_prot = newprot; change_protection(vma, start, end, newprot); - vm_stat_account(vma); + __vm_stat_account(mm, oldflags, vma->vm_file, -nrpages); + __vm_stat_account(mm, newflags, vma->vm_file, nrpages); return 0; fail: @@ -246,7 +248,7 @@ sys_mprotect(unsigned long start, size_t prev = vma; for (nstart = start ; ; ) { - unsigned int newflags; + unsigned long newflags; /* Here we know that vma->vm_start <= nstart < vma->vm_end. */ _