mm/madvise: don't perform madvise VMA walk for MADV_POPULATE_(READ|WRITE)
[linux-2.6-block.git] / mm / madvise.c
index 1a073fcc4c0c021496667619a20f6ee1afaef7c0..a2dd70c4a2e6b15fa9815f8c0b582367b61e1da0 100644 (file)
@@ -901,26 +901,19 @@ static long madvise_dontneed_free(struct vm_area_struct *vma,
                return -EINVAL;
 }
 
-static long madvise_populate(struct vm_area_struct *vma,
-                            struct vm_area_struct **prev,
-                            unsigned long start, unsigned long end,
-                            int behavior)
+static long madvise_populate(struct mm_struct *mm, unsigned long start,
+               unsigned long end, int behavior)
 {
        const bool write = behavior == MADV_POPULATE_WRITE;
-       struct mm_struct *mm = vma->vm_mm;
        int locked = 1;
        long pages;
 
-       *prev = vma;
-
        while (start < end) {
                /* Populate (prefault) page tables readable/writable. */
                pages = faultin_page_range(mm, start, end, write, &locked);
                if (!locked) {
                        mmap_read_lock(mm);
                        locked = 1;
-                       *prev = NULL;
-                       vma = NULL;
                }
                if (pages < 0) {
                        switch (pages) {
@@ -1021,9 +1014,6 @@ static int madvise_vma_behavior(struct vm_area_struct *vma,
        case MADV_DONTNEED:
        case MADV_DONTNEED_LOCKED:
                return madvise_dontneed_free(vma, prev, start, end, behavior);
-       case MADV_POPULATE_READ:
-       case MADV_POPULATE_WRITE:
-               return madvise_populate(vma, prev, start, end, behavior);
        case MADV_NORMAL:
                new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ;
                break;
@@ -1425,8 +1415,16 @@ int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int beh
        end = start + len;
 
        blk_start_plug(&plug);
-       error = madvise_walk_vmas(mm, start, end, behavior,
-                       madvise_vma_behavior);
+       switch (behavior) {
+       case MADV_POPULATE_READ:
+       case MADV_POPULATE_WRITE:
+               error = madvise_populate(mm, start, end, behavior);
+               break;
+       default:
+               error = madvise_walk_vmas(mm, start, end, behavior,
+                                         madvise_vma_behavior);
+               break;
+       }
        blk_finish_plug(&plug);
        if (write)
                mmap_write_unlock(mm);