mm: mmap_region: kill correct_wcount/inode, use allow_write_access()
[pandora-kernel.git] / mm / mmap.c
index 37a72e4..f04b71c 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1049,6 +1049,8 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 
                        if (!file->f_op || !file->f_op->mmap)
                                return -ENODEV;
+                       if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
+                               return -EINVAL;
                        break;
 
                default:
@@ -1057,6 +1059,8 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
        } else {
                switch (flags & MAP_TYPE) {
                case MAP_SHARED:
+                       if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
+                               return -EINVAL;
                        /*
                         * Ignore pgoff.
                         */
@@ -1201,11 +1205,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma, *prev;
-       int correct_wcount = 0;
        int error;
        struct rb_node **rb_link, *rb_parent;
        unsigned long charged = 0;
-       struct inode *inode =  file ? file->f_path.dentry->d_inode : NULL;
 
        /* Clear old maps */
        error = -ENOMEM;
@@ -1272,17 +1274,12 @@ munmap_back:
        INIT_LIST_HEAD(&vma->anon_vma_chain);
 
        if (file) {
-               error = -EINVAL;
-               if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
-                       goto free_vma;
                if (vm_flags & VM_DENYWRITE) {
                        error = deny_write_access(file);
                        if (error)
                                goto free_vma;
-                       correct_wcount = 1;
                }
-               vma->vm_file = file;
-               get_file(file);
+               vma->vm_file = get_file(file);
                error = file->f_op->mmap(file, vma);
                if (error)
                        goto unmap_and_free_vma;
@@ -1319,11 +1316,10 @@ munmap_back:
        }
 
        vma_link(mm, vma, prev, rb_link, rb_parent);
-       file = vma->vm_file;
-
        /* Once vma denies write, undo our temporary denial count */
-       if (correct_wcount)
-               atomic_inc(&inode->i_writecount);
+       if (vm_flags & VM_DENYWRITE)
+               allow_write_access(file);
+       file = vma->vm_file;
 out:
        perf_event_mmap(vma);
 
@@ -1337,8 +1333,8 @@ out:
        return addr;
 
 unmap_and_free_vma:
-       if (correct_wcount)
-               atomic_inc(&inode->i_writecount);
+       if (vm_flags & VM_DENYWRITE)
+               allow_write_access(file);
        vma->vm_file = NULL;
        fput(file);
 
@@ -1628,7 +1624,6 @@ EXPORT_SYMBOL(find_vma);
 
 /*
  * Same as find_vma, but also return a pointer to the previous VMA in *pprev.
- * Note: pprev is set to NULL when return value is NULL.
  */
 struct vm_area_struct *
 find_vma_prev(struct mm_struct *mm, unsigned long addr,
@@ -1637,7 +1632,16 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr,
        struct vm_area_struct *vma;
 
        vma = find_vma(mm, addr);
-       *pprev = vma ? vma->vm_prev : NULL;
+       if (vma) {
+               *pprev = vma->vm_prev;
+       } else {
+               struct rb_node *rb_node = mm->mm_rb.rb_node;
+               *pprev = NULL;
+               while (rb_node) {
+                       *pprev = rb_entry(rb_node, struct vm_area_struct, vm_rb);
+                       rb_node = rb_node->rb_right;
+               }
+       }
        return vma;
 }