Merge to Fedora kernel-2.6.6-1.422
[linux-2.6.git] / mm / mmap.c
index 03b30d1..cafada3 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -344,8 +344,9 @@ __insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
        validate_mm(mm);
 }
 
-static inline void __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
-                 struct vm_area_struct *prev)
+static inline void
+__vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
+               struct vm_area_struct *prev)
 {
        prev->vm_next = vma->vm_next;
        rb_erase(&vma->vm_rb, &mm->mm_rb);
@@ -772,15 +773,17 @@ unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
                        mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 
        if (flags & MAP_LOCKED) {
-               if (!capable(CAP_IPC_LOCK))
+               if (!can_do_mlock())
                        return -EPERM;
                vm_flags |= VM_LOCKED;
        }
        /* mlock MCL_FUTURE? */
        if (vm_flags & VM_LOCKED) {
-               unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+               unsigned long locked, lock_limit;
+               locked = mm->locked_vm << PAGE_SHIFT;
+               lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
                locked += len;
-               if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+               if (locked > lock_limit && !capable(CAP_IPC_LOCK))
                        return -EAGAIN;
        }
 
@@ -1384,6 +1387,7 @@ no_mmaps:
 static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
 {
        size_t len = area->vm_end - area->vm_start;
+       unsigned long old_end = area->vm_end;
 
        // area->vm_mm->total_vm -= len >> PAGE_SHIFT;
        vx_vmpages_sub(area->vm_mm, len >> PAGE_SHIFT);
@@ -1402,10 +1406,9 @@ static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
         */
        if (area->vm_start > area->vm_mm->non_executable_cache)
                area->vm_mm->non_executable_cache = area->vm_start;
-                                                                                                                                                                                                    
        remove_vm_struct(area);
        if (unlikely(area->vm_flags & VM_EXEC))
-               arch_remove_exec_range(mm, area->vm_end);
+               arch_remove_exec_range(mm, old_end);
 }
 
 /*
@@ -1494,11 +1497,8 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
        /* most fields are the same, copy all, and then fixup */
        *new = *vma;
 
-       if (new_below) {
-               if (vma->vm_flags & VM_EXEC)
-                       arch_remove_exec_range(mm, new->vm_end);
+       if (new_below)
                new->vm_end = addr;
-       }
        else {
                new->vm_start = addr;
                new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT);
@@ -1517,10 +1517,14 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
        if (new->vm_ops && new->vm_ops->open)
                new->vm_ops->open(new);
 
-       if (new_below)
+       if (new_below) {
+               unsigned long old_end = vma->vm_end;
+
                vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
                        ((addr - new->vm_start) >> PAGE_SHIFT), new);
-       else
+               if (vma->vm_flags & VM_EXEC)
+                       arch_remove_exec_range(mm, old_end);
+       } else
                vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
 
        return 0;
@@ -1636,9 +1640,11 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
         * mlock MCL_FUTURE?
         */
        if (mm->def_flags & VM_LOCKED) {
-               unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+               unsigned long locked, lock_limit;
+               locked = mm->locked_vm << PAGE_SHIFT;
+               lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
                locked += len;
-               if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+               if (locked > lock_limit && !capable(CAP_IPC_LOCK))
                        return -EAGAIN;
                /* vserver checks ? */
        }