Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
[sfrench/cifs-2.6.git] / mm / mmap.c
index 7afc7a7cec6f681001817ad6656d3a20d9ed53a7..0d40e66c841b2d2cad8e03ebc6d5e16491b0774b 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -93,7 +93,7 @@ atomic_t vm_committed_space = ATOMIC_INIT(0);
  * Note this is a helper function intended to be used by LSMs which
  * wish to use this logic.
  */
-int __vm_enough_memory(long pages, int cap_sys_admin)
+int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 {
        unsigned long free, allowed;
 
@@ -166,7 +166,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
 
        /* Don't let a single process grow too big:
           leave 3% of the size of this process for other processes */
-       allowed -= current->mm->total_vm / 32;
+       allowed -= mm->total_vm / 32;
 
        /*
         * cast `allowed' as a signed long because vm_committed_space
@@ -1029,6 +1029,40 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 }
 EXPORT_SYMBOL(do_mmap_pgoff);
 
+/*
+ * Some shared mappigns will want the pages marked read-only
+ * to track write events. If so, we'll downgrade vm_page_prot
+ * to the private version (using protection_map[] without the
+ * VM_SHARED bit).
+ */
+int vma_wants_writenotify(struct vm_area_struct *vma)
+{
+       unsigned int vm_flags = vma->vm_flags;
+
+       /* If it was private or non-writable, the write bit is already clear */
+       if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED)))
+               return 0;
+
+       /* The backer wishes to know when pages are first written to? */
+       if (vma->vm_ops && vma->vm_ops->page_mkwrite)
+               return 1;
+
+       /* The open routine did something to the protections already? */
+       if (pgprot_val(vma->vm_page_prot) !=
+           pgprot_val(protection_map[vm_flags &
+                   (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]))
+               return 0;
+
+       /* Specialty mapping? */
+       if (vm_flags & (VM_PFNMAP|VM_INSERTPAGE))
+               return 0;
+
+       /* Can the mapping track the dirty pages? */
+       return vma->vm_file && vma->vm_file->f_mapping &&
+               mapping_cap_account_dirty(vma->vm_file->f_mapping);
+}
+
+
 unsigned long mmap_region(struct file *file, unsigned long addr,
                          unsigned long len, unsigned long flags,
                          unsigned int vm_flags, unsigned long pgoff,
@@ -2043,7 +2077,7 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
        if (__vma && __vma->vm_start < vma->vm_end)
                return -ENOMEM;
        if ((vma->vm_flags & VM_ACCOUNT) &&
-            security_vm_enough_memory(vma_pages(vma)))
+            security_vm_enough_memory_mm(mm, vma_pages(vma)))
                return -ENOMEM;
        vma_link(mm, vma, prev, rb_link, rb_parent);
        return 0;