ksm: first tidy up madvise_vma()
authorHugh Dickins <hugh.dickins@tiscali.co.uk>
Tue, 22 Sep 2009 00:01:52 +0000 (17:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Sep 2009 14:17:31 +0000 (07:17 -0700)
madvise.c has several levels of switch statements, what to do in which?
Move MADV_DOFORK code down from madvise_vma() to madvise_behavior(), so
madvise_vma() can be a simple router, to madvise_behavior() by default.

vma->vm_flags is an unsigned long so use the same type for new_flags.  Add
missing comment lines to describe MADV_DONTFORK and MADV_DOFORK.

Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Signed-off-by: Chris Wright <chrisw@redhat.com>
Signed-off-by: Izik Eidus <ieidus@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/madvise.c

index 76eb419..66c3126 100644 (file)
@@ -41,7 +41,7 @@ static long madvise_behavior(struct vm_area_struct * vma,
        struct mm_struct * mm = vma->vm_mm;
        int error = 0;
        pgoff_t pgoff;
-       int new_flags = vma->vm_flags;
+       unsigned long new_flags = vma->vm_flags;
 
        switch (behavior) {
        case MADV_NORMAL:
@@ -57,6 +57,10 @@ static long madvise_behavior(struct vm_area_struct * vma,
                new_flags |= VM_DONTCOPY;
                break;
        case MADV_DOFORK:
+               if (vma->vm_flags & VM_IO) {
+                       error = -EINVAL;
+                       goto out;
+               }
                new_flags &= ~VM_DONTCOPY;
                break;
        }
@@ -211,37 +215,16 @@ static long
 madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
                unsigned long start, unsigned long end, int behavior)
 {
-       long error;
-
        switch (behavior) {
-       case MADV_DOFORK:
-               if (vma->vm_flags & VM_IO) {
-                       error = -EINVAL;
-                       break;
-               }
-       case MADV_DONTFORK:
-       case MADV_NORMAL:
-       case MADV_SEQUENTIAL:
-       case MADV_RANDOM:
-               error = madvise_behavior(vma, prev, start, end, behavior);
-               break;
        case MADV_REMOVE:
-               error = madvise_remove(vma, prev, start, end);
-               break;
-
+               return madvise_remove(vma, prev, start, end);
        case MADV_WILLNEED:
-               error = madvise_willneed(vma, prev, start, end);
-               break;
-
+               return madvise_willneed(vma, prev, start, end);
        case MADV_DONTNEED:
-               error = madvise_dontneed(vma, prev, start, end);
-               break;
-
+               return madvise_dontneed(vma, prev, start, end);
        default:
-               BUG();
-               break;
+               return madvise_behavior(vma, prev, start, end, behavior);
        }
-       return error;
 }
 
 static int
@@ -262,6 +245,7 @@ madvise_behavior_valid(int behavior)
                return 0;
        }
 }
+
 /*
  * The madvise(2) system call.
  *
@@ -286,6 +270,9 @@ madvise_behavior_valid(int behavior)
  *             so the kernel can free resources associated with it.
  *  MADV_REMOVE - the application wants to free up the given range of
  *             pages and associated backing store.
+ *  MADV_DONTFORK - omit this area from child's address space when forking:
+ *             typically, to avoid COWing pages pinned by get_user_pages().
+ *  MADV_DOFORK - cancel MADV_DONTFORK: no longer omit this area when forking.
  *
  * return values:
  *  zero    - success