[PATCH] madvise MADV_DONTFORK/MADV_DOFORK
authorMichael S. Tsirkin <mst@mellanox.co.il>
Tue, 14 Feb 2006 21:53:08 +0000 (13:53 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 15 Feb 2006 00:09:34 +0000 (16:09 -0800)
Currently, copy-on-write may change the physical address of a page even if the
user requested that the page is pinned in memory (either by mlock or by
get_user_pages).  This happens if the process forks meanwhile, and the parent
writes to that page.  As a result, the page is orphaned: in case of
get_user_pages, the application will never see any data hardware DMA's into
this page after the COW.  In case of mlock'd memory, the parent is not getting
the realtime/security benefits of mlock.

In particular, this affects the Infiniband modules which do DMA from and into
user pages all the time.

This patch adds madvise options to control whether memory range is inherited
across fork.  Useful e.g.  for when hardware is doing DMA from/into these
pages.  Could also be useful to an application wanting to speed up its forks
by cutting large areas out of consideration.

Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Acked-by: Hugh Dickins <hugh@veritas.com>
Cc: Michael Kerrisk <mtk-manpages@gmx.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
21 files changed:
include/asm-alpha/mman.h
include/asm-arm/mman.h
include/asm-arm26/mman.h
include/asm-cris/mman.h
include/asm-frv/mman.h
include/asm-h8300/mman.h
include/asm-i386/mman.h
include/asm-ia64/mman.h
include/asm-m32r/mman.h
include/asm-m68k/mman.h
include/asm-mips/mman.h
include/asm-parisc/mman.h
include/asm-powerpc/mman.h
include/asm-s390/mman.h
include/asm-sh/mman.h
include/asm-sparc/mman.h
include/asm-sparc64/mman.h
include/asm-v850/mman.h
include/asm-x86_64/mman.h
include/asm-xtensa/mman.h
mm/madvise.c

index f6439532a262d45e2ff47655edfd87cb9fcf55fb..a21515c16a431b861ab37ce8e71df8b79d6d93b6 100644 (file)
@@ -43,6 +43,8 @@
 #define        MADV_SPACEAVAIL 5               /* ensure resources are available */
 #define MADV_DONTNEED  6               /* don't need these pages */
 #define MADV_REMOVE    7               /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index f0bebca2ac214a5b6b87dc8413c18b3cd9115ceb..693ed859e6324ff65fb26beea773291cedfd006a 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 0ed7780541fa1b27abba46b8541bcb6cf583d1c6..2096c50df8880ed104975f366bfd1b81bbe3c8e7 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 5a382b8bf3f738effedd851b6887f7ce4197817b..deddfb239ff55aa3af5d5e1f929fc6744c0fa1f1 100644 (file)
@@ -38,6 +38,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 8af4a41c255e113b6bf38b37fb0eafb26e312f65..d3bca306da82b751fe56c149fdea61da459d5ad8 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 744a8fb485c230780ff6256abc483a58bab647b2..ac0346f7d11da1fbdde8b1c661b6fa24a7096fde 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index ba4941e6f643213f39bcff3379259cdadf8584d3..ab2339a1d807e670d24becedebed92c3e068f68f 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 828beb24a20ec7837fe7a00dde7c4b8b93bbe941..357ebb780cc0f7378a990751373a487e5c77b723 100644 (file)
@@ -44,6 +44,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 12e29747bc84a510163f6e948f3d6834047e0c7c..6b02fe3fcff299c7dbeacb22e99f32404606e662 100644 (file)
@@ -38,6 +38,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index ea262ab88b3bb547761227d0a039e7800674bc4c..efd12bc4ccb7e4119529a2d2ac96180fb7353bfd 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index dd17c8bd62a1cbc4450db3b21035f8de94826639..6d01e26830fa55391b7feffb9d66d8d27f6c0609 100644 (file)
@@ -66,6 +66,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 736b0abcac052b1ad468ff0362bfe8e3173c531a..a381cf5c8f555c9429e1177d4bc983fc42dc9107 100644 (file)
@@ -49,6 +49,8 @@
 #define MADV_4M_PAGES   22              /* Use 4 Megabyte pages */
 #define MADV_16M_PAGES  24              /* Use 16 Megabyte pages */
 #define MADV_64M_PAGES  26              /* Use 64 Megabyte pages */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index a2e34c21b44f8f09455dad99aef78285d166da1a..fcff25d13f139d93330c273534f137dd0f0a00d3 100644 (file)
@@ -45,6 +45,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index c8d5409b5d563c383e9fa4f8378504b41c992473..d41ca1477010b9691e7d2150a0e8872948a5d0f2 100644 (file)
@@ -44,6 +44,8 @@
 #define MADV_WILLNEED  0x3              /* pre-fault pages */
 #define MADV_DONTNEED  0x4              /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 693bd55a37104f543a2c5e3a21878bbc5cd3d395..0e08d0573abcb5ed46ddea0b20b0f51d14d488c5 100644 (file)
@@ -36,6 +36,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 98435ad8619e0b0b5f5cd9aa882de51d6ea89948..4a298b2be8591d253a293824ac67afa78b2f848b 100644 (file)
@@ -55,6 +55,8 @@
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_FREE      0x5             /* (Solaris) contents can be freed */
 #define MADV_REMOVE    0x6             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index cb4b6156194dbe12dc92adfba8c3247400ebd0f8..d705ec92da8b03fe9fe2445ace035e51de507eff 100644 (file)
@@ -55,6 +55,8 @@
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_FREE      0x5             /* (Solaris) contents can be freed */
 #define MADV_REMOVE    0x6             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index edc79965193aa589e6810b35903fb7262c404927..7b851c310e41de6ce3362f5c941e2b0a81ec4078 100644 (file)
@@ -33,6 +33,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index d0e97b74f73591d0e430719f0861dc00dda1d224..b699a38c1c3ce751f76a19a9a8171d2df80a3b66 100644 (file)
@@ -37,6 +37,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index 082a7504925ed5bebeda7b910b25de6bc58075c1..e2d7afb679c803bad52d4413d45980abc7504e49 100644 (file)
@@ -73,6 +73,8 @@
 #define MADV_WILLNEED  0x3             /* pre-fault pages */
 #define MADV_DONTNEED  0x4             /* discard these pages */
 #define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_DONTFORK  0x30            /* dont inherit across fork */
+#define MADV_DOFORK    0x31            /* do inherit across fork */
 
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
index ae0ae3ea299a7a83b72939236ef4931eb5ac16d0..af3d573b014122f7fd2a99c3ee90c3826f70457f 100644 (file)
@@ -22,16 +22,23 @@ 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 & ~VM_READHINTMASK;
+       int new_flags = vma->vm_flags;
 
        switch (behavior) {
+       case MADV_NORMAL:
+               new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ;
+               break;
        case MADV_SEQUENTIAL:
-               new_flags |= VM_SEQ_READ;
+               new_flags = (new_flags & ~VM_RAND_READ) | VM_SEQ_READ;
                break;
        case MADV_RANDOM:
-               new_flags |= VM_RAND_READ;
+               new_flags = (new_flags & ~VM_SEQ_READ) | VM_RAND_READ;
                break;
-       default:
+       case MADV_DONTFORK:
+               new_flags |= VM_DONTCOPY;
+               break;
+       case MADV_DOFORK:
+               new_flags &= ~VM_DONTCOPY;
                break;
        }
 
@@ -177,6 +184,12 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
        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: