mm/vma: introduce VM_ACCESS_FLAGS
[linux-2.6-microblaze.git] / mm / mmap.c
index d681a20..f609e9e 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -53,6 +53,9 @@
 #include <asm/tlb.h>
 #include <asm/mmu_context.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/mmap.h>
+
 #include "internal.h"
 
 #ifndef arch_mmap_check
@@ -1221,7 +1224,7 @@ static int anon_vma_compatible(struct vm_area_struct *a, struct vm_area_struct *
        return a->vm_end == b->vm_start &&
                mpol_equal(vma_policy(a), vma_policy(b)) &&
                a->vm_file == b->vm_file &&
-               !((a->vm_flags ^ b->vm_flags) & ~(VM_READ|VM_WRITE|VM_EXEC|VM_SOFTDIRTY)) &&
+               !((a->vm_flags ^ b->vm_flags) & ~(VM_ACCESS_FLAGS | VM_SOFTDIRTY)) &&
                b->vm_pgoff == a->vm_pgoff + ((b->vm_start - a->vm_start) >> PAGE_SHIFT);
 }
 
@@ -1457,7 +1460,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
                         * with MAP_SHARED to preserve backward compatibility.
                         */
                        flags &= LEGACY_MAP_MASK;
-                       /* fall through */
+                       fallthrough;
                case MAP_SHARED_VALIDATE:
                        if (flags & ~flags_mask)
                                return -EOPNOTSUPP;
@@ -1484,8 +1487,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
                        vm_flags |= VM_SHARED | VM_MAYSHARE;
                        if (!(file->f_mode & FMODE_WRITE))
                                vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
-
-                       /* fall through */
+                       fallthrough;
                case MAP_PRIVATE:
                        if (!(file->f_mode & FMODE_READ))
                                return -EACCES;
@@ -1848,7 +1850,7 @@ unacct_error:
        return error;
 }
 
-unsigned long unmapped_area(struct vm_unmapped_area_info *info)
+static unsigned long unmapped_area(struct vm_unmapped_area_info *info)
 {
        /*
         * We implement the search by looking for an rbtree node that
@@ -1951,7 +1953,7 @@ found:
        return gap_start;
 }
 
-unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
+static unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
@@ -2050,6 +2052,27 @@ found_highest:
        return gap_end;
 }
 
+/*
+ * Search for an unmapped address range.
+ *
+ * We are looking for a range that:
+ * - does not intersect with any VMA;
+ * - is contained within the [low_limit, high_limit) interval;
+ * - is at least the desired size.
+ * - satisfies (begin_addr & align_mask) == (align_offset & align_mask)
+ */
+unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
+{
+       unsigned long addr;
+
+       if (info->flags & VM_UNMAPPED_AREA_TOPDOWN)
+               addr = unmapped_area_topdown(info);
+       else
+               addr = unmapped_area(info);
+
+       trace_vm_unmapped_area(addr, info);
+       return addr;
+}
 
 #ifndef arch_get_mmap_end
 #define arch_get_mmap_end(addr)        (TASK_SIZE)
@@ -2100,6 +2123,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        info.low_limit = mm->mmap_base;
        info.high_limit = mmap_end;
        info.align_mask = 0;
+       info.align_offset = 0;
        return vm_unmapped_area(&info);
 }
 #endif
@@ -2141,6 +2165,7 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
        info.low_limit = max(PAGE_SIZE, mmap_min_addr);
        info.high_limit = arch_get_mmap_base(addr, mm->mmap_base);
        info.align_mask = 0;
+       info.align_offset = 0;
        addr = vm_unmapped_area(&info);
 
        /*
@@ -2334,8 +2359,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                gap_addr = TASK_SIZE;
 
        next = vma->vm_next;
-       if (next && next->vm_start < gap_addr &&
-                       (next->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) {
+       if (next && next->vm_start < gap_addr && vma_is_accessible(next)) {
                if (!(next->vm_flags & VM_GROWSUP))
                        return -ENOMEM;
                /* Check that both stack segments have the same anon_vma? */
@@ -2416,7 +2440,7 @@ int expand_downwards(struct vm_area_struct *vma,
        prev = vma->vm_prev;
        /* Check that both stack segments have the same anon_vma? */
        if (prev && !(prev->vm_flags & VM_GROWSDOWN) &&
-                       (prev->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) {
+                       vma_is_accessible(prev)) {
                if (address - prev->vm_end < stack_guard_gap)
                        return -ENOMEM;
        }