[PATCH] madvise/mincore against 2.3.34

Chuck Lever (cel@monkey.org)
Tue, 21 Dec 1999 16:14:04 -0500 (EST)


linus-

i've removed "vma->vm_rd_behavior" in favor of using bits in vm_flags.
vm_flags is now a 32-bit field. i've also removed parts of the patch that
touch anonymous maps and stack areas, since those don't get paged in by
filemap_nopage. here's the patch against 2.3.34. tested briefly here,
all appears to work.

diff -ruN linux-ref/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- linux-ref/arch/alpha/kernel/osf_sys.c Thu Nov 4 14:34:10 1999
+++ linux/arch/alpha/kernel/osf_sys.c Tue Dec 21 16:03:33 1999
@@ -204,15 +204,6 @@
return prio;
}

-
-/*
- * Heh. As documented by DEC..
- */
-asmlinkage unsigned long sys_madvise(void)
-{
- return 0;
-}
-
/*
* No need to acquire the kernel lock, we're local..
*/
diff -ruN linux-ref/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-ref/arch/i386/kernel/entry.S Tue Dec 21 13:58:56 1999
+++ linux/arch/i386/kernel/entry.S Tue Dec 21 16:03:34 1999
@@ -598,7 +598,9 @@
.long SYMBOL_NAME(sys_stat64) /* 195 */
.long SYMBOL_NAME(sys_lstat64)
.long SYMBOL_NAME(sys_fstat64)
-
+ .long SYMBOL_NAME(sys_madvise)
+ .long SYMBOL_NAME(sys_mincore)
+ /* 200 */

/*
* NOTE!! This doesn't have to be exact - we just have
@@ -606,6 +608,6 @@
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-197
+ .rept NR_syscalls-199
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff -ruN linux-ref/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- linux-ref/arch/m68k/kernel/entry.S Thu Nov 4 15:01:55 1999
+++ linux/arch/m68k/kernel/entry.S Tue Dec 21 16:03:34 1999
@@ -600,6 +600,8 @@
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
+ .long SYMBOL_NAME(sys_madvise)
+ .long SYMBOL_NAME(sys_mincore)

.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
.long SYMBOL_NAME(sys_ni_syscall)
diff -ruN linux-ref/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h
--- linux-ref/arch/mips/kernel/irix5sys.h Thu Nov 4 14:09:50 1999
+++ linux/arch/mips/kernel/irix5sys.h Tue Dec 21 16:03:34 1999
@@ -157,7 +157,7 @@
SYS(sys_munmap, 2) /* 1135 munmap() V*/
SYS(sys_mprotect, 3) /* 1136 mprotect() V*/
SYS(sys_msync, 4) /* 1137 msync() V*/
-SYS(irix_madvise, 3) /* 1138 madvise() DC*/
+SYS(sys_madvise, 3) /* 1138 madvise() V*/
SYS(irix_pagelock, 3) /* 1139 pagelock() IV*/
SYS(irix_getpagesize, 0) /* 1140 getpagesize() V*/
SYS(irix_quotactl, 0) /* 1141 quotactl() V*/
diff -ruN linux-ref/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- linux-ref/arch/mips/kernel/syscalls.h Thu Nov 4 14:09:51 1999
+++ linux/arch/mips/kernel/syscalls.h Tue Dec 21 16:03:34 1999
@@ -223,5 +223,7 @@
SYS(sys_capset, 2) /* 4205 */
SYS(sys_sigaltstack, 2)
SYS(sys_sendfile, 3)
-SYS(sys_ni_syscall, 0)
-SYS(sys_ni_syscall, 0)
+SYS(sys_ni_syscall, 0) /* streams1 */
+SYS(sys_ni_syscall, 0) /* streams2 */
+SYS(sys_madvise, 3) /* 4210 */
+SYS(sys_mincore, 3)
diff -ruN linux-ref/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- linux-ref/arch/mips/kernel/sysirix.c Thu Nov 4 14:09:51 1999
+++ linux/arch/mips/kernel/sysirix.c Tue Dec 21 16:03:34 1999
@@ -1136,15 +1136,6 @@
return retval;
}

-asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
-{
- lock_kernel();
- printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n",
- current->comm, current->pid, addr, len, behavior);
- unlock_kernel();
- return -EINVAL;
-}
-
asmlinkage int irix_pagelock(char *addr, int len, int op)
{
lock_kernel();
diff -ruN linux-ref/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- linux-ref/arch/ppc/kernel/misc.S Fri Dec 10 13:24:07 1999
+++ linux/arch/ppc/kernel/misc.S Tue Dec 21 16:03:34 1999
@@ -1068,4 +1068,6 @@
.long sys_ni_syscall /* streams2 */
.long sys_vfork
.long sys_getrlimit /* 190 */
- .space (NR_syscalls-190)*4
+ .long sys_madvise
+ .long sys_mincore
+ .space (NR_syscalls-192)*4
diff -ruN linux-ref/include/asm-alpha/mman.h linux/include/asm-alpha/mman.h
--- linux-ref/include/asm-alpha/mman.h Sun Jan 25 19:31:47 1998
+++ linux/include/asm-alpha/mman.h Tue Dec 21 16:03:34 1999
@@ -31,6 +31,12 @@
#define MCL_CURRENT 8192 /* lock all currently mapped pages */
#define MCL_FUTURE 16384 /* lock all additions to address space */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- linux-ref/include/asm-alpha/unistd.h Tue Dec 21 13:58:59 1999
+++ linux/include/asm-alpha/unistd.h Tue Dec 21 16:03:34 1999
@@ -79,7 +79,7 @@
#define __NR_madvise 75
#define __NR_vhangup 76
#define __NR_osf_kmodcall 77 /* not implemented */
-#define __NR_osf_mincore 78 /* not implemented */
+#define __NR_mincore 78
#define __NR_getgroups 79
#define __NR_setgroups 80
#define __NR_osf_old_getpgrp 81 /* not implemented */
diff -ruN linux-ref/include/asm-arm/mman.h linux/include/asm-arm/mman.h
--- linux-ref/include/asm-arm/mman.h Tue Jan 20 19:39:42 1998
+++ linux/include/asm-arm/mman.h Tue Dec 21 16:03:34 1999
@@ -25,6 +25,12 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- linux-ref/include/asm-arm/unistd.h Tue Dec 21 13:58:59 1999
+++ linux/include/asm-arm/unistd.h Tue Dec 21 16:03:34 1999
@@ -205,6 +205,8 @@
#define __NR_stat64 (__NR_SYSCALL_BASE+195)
#define __NR_lstat64 (__NR_SYSCALL_BASE+196)
#define __NR_fstat64 (__NR_SYSCALL_BASE+197)
+#define __NR_madvise (__NR_SYSCALL_BASE+198)
+#define __NR_mincore (__NR_SYSCALL_BASE+199)

#define __sys2(x) #x
#define __sys1(x) __sys2(x)
diff -ruN linux-ref/include/asm-i386/mman.h linux/include/asm-i386/mman.h
--- linux-ref/include/asm-i386/mman.h Mon Oct 7 01:55:48 1996
+++ linux/include/asm-i386/mman.h Tue Dec 21 16:03:34 1999
@@ -25,6 +25,12 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- linux-ref/include/asm-i386/unistd.h Tue Dec 21 13:58:59 1999
+++ linux/include/asm-i386/unistd.h Tue Dec 21 16:03:34 1999
@@ -202,6 +202,9 @@
#define __NR_stat64 195
#define __NR_lstat64 196
#define __NR_fstat64 197
+#define __NR_madvise 198
+#define __NR_madvise1 198 /* remove this, once glibc has real madvise */
+#define __NR_mincore 199

/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */

diff -ruN linux-ref/include/asm-m68k/mman.h linux/include/asm-m68k/mman.h
--- linux-ref/include/asm-m68k/mman.h Fri Nov 22 08:56:36 1996
+++ linux/include/asm-m68k/mman.h Tue Dec 21 16:03:34 1999
@@ -25,6 +25,12 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h
--- linux-ref/include/asm-m68k/unistd.h Tue Dec 21 13:58:59 1999
+++ linux/include/asm-m68k/unistd.h Tue Dec 21 16:03:34 1999
@@ -201,6 +201,8 @@
#define __NR_stat64 195
#define __NR_lstat64 196
#define __NR_fstat64 197
+#define __NR_madvise 198
+#define __NR_mincore 199

/* user-visible error numbers are in the range -1 - -122: see
<asm-m68k/errno.h> */
diff -ruN linux-ref/include/asm-mips/mman.h linux/include/asm-mips/mman.h
--- linux-ref/include/asm-mips/mman.h Thu Jun 26 15:33:40 1997
+++ linux/include/asm-mips/mman.h Tue Dec 21 16:03:34 1999
@@ -56,6 +56,15 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */

+/*
+ * Flags for madvise
+ */
+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- linux-ref/include/asm-mips/unistd.h Thu Nov 4 14:10:00 1999
+++ linux/include/asm-mips/unistd.h Tue Dec 21 16:03:34 1999
@@ -1196,11 +1196,13 @@
#define __NR_sendfile (__NR_Linux + 207)
#define __NR_getpmsg (__NR_Linux + 208)
#define __NR_putpmsg (__NR_Linux + 209)
+#define __NR_madvise (__NR_Linux + 210)
+#define __NR_mincore (__NR_Linux + 211)

/*
* Offset of the last Linux flavoured syscall
*/
-#define __NR_Linux_syscalls 209
+#define __NR_Linux_syscalls 211

#ifndef _LANGUAGE_ASSEMBLY

diff -ruN linux-ref/include/asm-ppc/mman.h linux/include/asm-ppc/mman.h
--- linux-ref/include/asm-ppc/mman.h Wed Dec 18 03:54:09 1996
+++ linux/include/asm-ppc/mman.h Tue Dec 21 16:03:35 1999
@@ -25,6 +25,12 @@
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
#define MCL_FUTURE 0x4000 /* lock all additions to address space */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- linux-ref/include/asm-ppc/unistd.h Fri Dec 10 13:24:09 1999
+++ linux/include/asm-ppc/unistd.h Tue Dec 21 16:03:35 1999
@@ -194,7 +194,9 @@
#define __NR_getpmsg 187 /* some people actually want streams */
#define __NR_putpmsg 188 /* some people actually want streams */
#define __NR_vfork 189
-#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
+#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
+#define __NR_madvise 191
+#define __NR_mincore 192

#define __NR(n) #n

diff -ruN linux-ref/include/asm-sh/mman.h linux/include/asm-sh/mman.h
--- linux-ref/include/asm-sh/mman.h Thu Nov 4 14:54:55 1999
+++ linux/include/asm-sh/mman.h Tue Dec 21 16:03:35 1999
@@ -25,6 +25,12 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FILE 0
diff -ruN linux-ref/include/asm-sh/unistd.h linux/include/asm-sh/unistd.h
--- linux-ref/include/asm-sh/unistd.h Thu Nov 4 15:48:00 1999
+++ linux/include/asm-sh/unistd.h Tue Dec 21 16:03:35 1999
@@ -200,6 +200,8 @@
#define __NR_streams1 188 /* some people actually want it */
#define __NR_streams2 189 /* some people actually want it */
#define __NR_vfork 190
+#define __NR_madvise 191
+#define __NR_mincore 192

/* user-visible error numbers are in the range -1 - -125: see <asm-sh/errno.h> */

diff -ruN linux-ref/include/asm-sparc/mman.h linux/include/asm-sparc/mman.h
--- linux-ref/include/asm-sparc/mman.h Sat Nov 9 03:29:41 1996
+++ linux/include/asm-sparc/mman.h Tue Dec 21 16:03:35 1999
@@ -31,6 +31,12 @@
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
#define MCL_FUTURE 0x4000 /* lock all additions to address space */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
* XXX calls.
*/
diff -ruN linux-ref/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- linux-ref/include/asm-sparc/unistd.h Thu Apr 22 22:24:52 1999
+++ linux/include/asm-sparc/unistd.h Tue Dec 21 16:03:35 1999
@@ -90,10 +90,10 @@
/* #define __NR_vadvise 72 SunOS Specific */
#define __NR_munmap 73 /* Common */
#define __NR_mprotect 74 /* Common */
-/* #define __NR_madvise 75 SunOS Specific */
+#define __NR_madvise 75 /* Common */
#define __NR_vhangup 76 /* Common */
/* #define __NR_ni_syscall 77 ENOSYS under SunOS */
-/* #define __NR_mincore 78 SunOS Specific */
+#define __NR_mincore 78 /* Common */
#define __NR_getgroups 79 /* Common */
#define __NR_setgroups 80 /* Common */
#define __NR_getpgrp 81 /* Common */
diff -ruN linux-ref/include/asm-sparc64/mman.h linux/include/asm-sparc64/mman.h
--- linux-ref/include/asm-sparc64/mman.h Fri Dec 13 04:37:47 1996
+++ linux/include/asm-sparc64/mman.h Tue Dec 21 16:03:35 1999
@@ -31,6 +31,12 @@
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
#define MCL_FUTURE 0x4000 /* lock all additions to address space */

+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* free these pages */
+
/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
* XXX calls.
*/
diff -ruN linux-ref/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- linux-ref/include/asm-sparc64/unistd.h Thu Nov 4 14:34:33 1999
+++ linux/include/asm-sparc64/unistd.h Tue Dec 21 16:03:35 1999
@@ -90,10 +90,10 @@
/* #define __NR_vadvise 72 SunOS Specific */
#define __NR_munmap 73 /* Common */
#define __NR_mprotect 74 /* Common */
-/* #define __NR_madvise 75 SunOS Specific */
+#define __NR_madvise 75 /* Common */
#define __NR_vhangup 76 /* Common */
/* #define __NR_ni_syscall 77 ENOSYS under SunOS */
-/* #define __NR_mincore 78 SunOS Specific */
+#define __NR_mincore 78 /* Common */
#define __NR_getgroups 79 /* Common */
#define __NR_setgroups 80 /* Common */
#define __NR_getpgrp 81 /* Common */
diff -ruN linux-ref/include/linux/mm.h linux/include/linux/mm.h
--- linux-ref/include/linux/mm.h Thu Dec 16 16:14:05 1999
+++ linux/include/linux/mm.h Tue Dec 21 16:03:35 1999
@@ -44,7 +44,7 @@
struct vm_area_struct *vm_next;

pgprot_t vm_page_prot;
- unsigned short vm_flags;
+ unsigned int vm_flags;

/* AVL tree of VM areas per task, sorted by address */
short vm_avl_height;
@@ -60,32 +60,42 @@
struct vm_operations_struct * vm_ops;
unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
struct file * vm_file;
+ unsigned long vm_raend;
void * vm_private_data; /* was vm_pte (shared mem) */
};

/*
* vm_flags..
*/
-#define VM_READ 0x0001 /* currently active flags */
-#define VM_WRITE 0x0002
-#define VM_EXEC 0x0004
-#define VM_SHARED 0x0008
-
-#define VM_MAYREAD 0x0010 /* limits for mprotect() etc */
-#define VM_MAYWRITE 0x0020
-#define VM_MAYEXEC 0x0040
-#define VM_MAYSHARE 0x0080
-
-#define VM_GROWSDOWN 0x0100 /* general info on the segment */
-#define VM_GROWSUP 0x0200
-#define VM_SHM 0x0400 /* shared memory area, don't swap out */
-#define VM_DENYWRITE 0x0800 /* ETXTBSY on write attempts.. */
-
-#define VM_EXECUTABLE 0x1000
-#define VM_LOCKED 0x2000
-#define VM_IO 0x4000 /* Memory mapped I/O or similar */
-
-#define VM_STACK_FLAGS 0x0177
+#define VM_READ 0x00000001 /* currently active flags */
+#define VM_WRITE 0x00000002
+#define VM_EXEC 0x00000004
+#define VM_SHARED 0x00000008
+
+#define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */
+#define VM_MAYWRITE 0x00000020
+#define VM_MAYEXEC 0x00000040
+#define VM_MAYSHARE 0x00000080
+
+#define VM_GROWSDOWN 0x00000100 /* general info on the segment */
+#define VM_GROWSUP 0x00000200
+#define VM_SHM 0x00000400 /* shared memory area, don't swap out */
+#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */
+
+#define VM_EXECUTABLE 0x00001000
+#define VM_LOCKED 0x00002000
+#define VM_IO 0x00004000 /* Memory mapped I/O or similar */
+
+#define VM_SEQ_READ 0x00010000 /* App will access data sequentially */
+#define VM_RAND_READ 0x00020000 /* App will not benefit from clustered reads */
+
+#define VM_STACK_FLAGS 0x00000177
+
+#define VM_READHINTMASK (VM_SEQ_READ | VM_RAND_READ)
+#define VM_ClearReadHint(v) (v)->vm_flags &= ~VM_READHINTMASK
+#define VM_NormalReadHint(v) (!((v)->vm_flags & VM_READHINTMASK))
+#define VM_SequentialReadHint(v) ((v)->vm_flags & VM_SEQ_READ)
+#define VM_RandomReadHint(v) ((v)->vm_flags & VM_RAND_READ)

/*
* mapping from the currently active vm_flags protection bits (the
@@ -439,6 +449,11 @@
extern unsigned long page_unuse(struct page *);
extern int shrink_mmap(int, int);
extern void truncate_inode_pages(struct inode *, loff_t);
+extern long madvise_dontneed(struct vm_area_struct *, unsigned long,
+ unsigned long);
+extern long madvise_willneed(struct vm_area_struct *, unsigned long,
+ unsigned long);
+

/*
* GFP bitmasks..
diff -ruN linux-ref/kernel/fork.c linux/kernel/fork.c
--- linux-ref/kernel/fork.c Wed Nov 24 16:47:44 1999
+++ linux/kernel/fork.c Tue Dec 21 16:03:35 1999
@@ -247,6 +247,7 @@
goto fail_nomem;
*tmp = *mpnt;
tmp->vm_flags &= ~VM_LOCKED;
+ tmp->vm_raend = 0;
tmp->vm_mm = mm;
mm->map_count++;
tmp->vm_next = NULL;
diff -ruN linux-ref/mm/filemap.c linux/mm/filemap.c
--- linux-ref/mm/filemap.c Tue Dec 21 13:59:00 1999
+++ linux/mm/filemap.c Tue Dec 21 16:03:35 1999
@@ -19,12 +19,14 @@
#include <linux/blkdev.h>
#include <linux/file.h>
#include <linux/swapctl.h>
+#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/mm.h>

#include <asm/pgalloc.h>
#include <asm/uaccess.h>
+#include <asm/mman.h>

#include <linux/highmem.h>

@@ -38,6 +40,8 @@
* page-cache, 21.05.1999, Ingo Molnar <mingo@redhat.com>
*
* SMP-threaded pagemap-LRU 1999, Andrea Arcangeli <andrea@suse.de>
+ *
+ * madvise(2) and mincore(2), Chuck Lever <chuckl@netscape.com>
*/

atomic_t page_cache_size = ATOMIC_INIT(0);
@@ -54,6 +58,9 @@
#define CLUSTER_PAGES (1 << page_cluster)
#define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster)

+#define filesize_in_pages(f) \
+ (((f)->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
void __add_page_to_hash_queue(struct page * page, struct page **p)
{
atomic_inc(&page_cache_size);
@@ -549,24 +556,22 @@

/*
* Read in an entire cluster at once. A cluster is usually a 64k-
- * aligned block that includes the address requested in "offset."
+ * aligned block that includes the page requested in "offset."
*/
-static int read_cluster_nonblocking(struct file * file, unsigned long offset)
+static int read_cluster_nonblocking(struct file * file, unsigned long offset,
+ unsigned long filesize)
{
- int error = 0;
- unsigned long filesize = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
unsigned long pages = CLUSTER_PAGES;

offset = CLUSTER_OFFSET(offset);
while ((pages-- > 0) && (offset < filesize)) {
- error = page_cache_read(file, offset);
- if (error >= 0)
- offset ++;
- else
- break;
+ int error = page_cache_read(file, offset);
+ if (error < 0)
+ return error;
+ offset ++;
}

- return error;
+ return 0;
}

/*
@@ -704,6 +709,502 @@
return page;
}

+/*
+ * The madvise(2) system call.
+ *
+ * Applications can use madvise() to advise the kernel how it should
+ * handle paging I/O in this VM area. The idea is to help the kernel
+ * use appropriate read-ahead and caching techniques. The information
+ * provided is advisory only, and can be safely disregarded by the
+ * kernel without affecting the correct operation of the application.
+ *
+ * behavior values:
+ * MADV_NORMAL - the default behavior is to read clusters. This
+ * results in some read-ahead and read-behind.
+ * MADV_RANDOM - the system should read the minimum amount of data
+ * on any access, since it is unlikely that the appli-
+ * cation will need more than what it asks for.
+ * MADV_SEQUENTIAL - pages in the given range will probably be accessed
+ * once, so they can be aggressively read ahead, and
+ * can be freed soon after they are accessed.
+ * MADV_WILLNEED - the application is notifying the system to read
+ * some pages ahead.
+ * MADV_DONTNEED - the application is finished with the given range,
+ * so the kernel can free resources associated with it.
+ *
+ * return values:
+ * zero = success
+ * -1 = some error occurred, errno value set (see below).
+ *
+ * errno values:
+ * EINVAL - start + len < 0, start is not page-aligned,
+ * "behavior" is not a valid value, or application
+ * is attempting to release locked or shared pages.
+ * ENOMEM - addresses in the specified range are not currently
+ * mapped, or are outside the AS of the process,
+ * or the kernel has exhausted its memory resources.
+ * EIO - an I/O error occurred while paging in data.
+ * EBADF - map exists, but area maps something that isn't a file.
+ */
+
+static inline void setup_read_behavior(struct vm_area_struct * vma,
+ int behavior)
+{
+ vma->vm_flags &= ~VM_READHINTMASK;
+ switch(behavior) {
+ case MADV_SEQUENTIAL:
+ vma->vm_flags |= VM_SEQ_READ;
+ break;
+ case MADV_RANDOM:
+ vma->vm_flags |= VM_RAND_READ;
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+static long madvise_fixup_start(struct vm_area_struct * vma,
+ unsigned long end, int behavior)
+{
+ struct vm_area_struct * n;
+
+ n = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!n)
+ return -ENOMEM;
+ *n = *vma;
+ n->vm_end = end;
+ setup_read_behavior(n, behavior);
+ n->vm_raend = 0;
+ if (n->vm_file)
+ get_file(n->vm_file);
+ if (n->vm_ops && n->vm_ops->open)
+ n->vm_ops->open(n);
+ vmlist_modify_lock(vma->vm_mm);
+ vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
+ vma->vm_start = end;
+ insert_vm_struct(current->mm, n);
+ vmlist_modify_unlock(vma->vm_mm);
+ return 0;
+}
+
+static long madvise_fixup_end(struct vm_area_struct * vma,
+ unsigned long start, int behavior)
+{
+ struct vm_area_struct * n;
+
+ n = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!n)
+ return -ENOMEM;
+ *n = *vma;
+ n->vm_start = start;
+ n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
+ setup_read_behavior(n, behavior);
+ n->vm_raend = 0;
+ if (n->vm_file)
+ get_file(n->vm_file);
+ if (n->vm_ops && n->vm_ops->open)
+ n->vm_ops->open(n);
+ vmlist_modify_lock(vma->vm_mm);
+ vma->vm_end = start;
+ insert_vm_struct(current->mm, n);
+ vmlist_modify_unlock(vma->vm_mm);
+ return 0;
+}
+
+static long madvise_fixup_middle(struct vm_area_struct * vma,
+ unsigned long start, unsigned long end, int behavior)
+{
+ struct vm_area_struct * left, * right;
+
+ left = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!left)
+ return -ENOMEM;
+ right = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!right) {
+ kmem_cache_free(vm_area_cachep, left);
+ return -ENOMEM;
+ }
+ *left = *vma;
+ *right = *vma;
+ left->vm_end = start;
+ right->vm_start = end;
+ right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
+ left->vm_raend = 0;
+ right->vm_raend = 0;
+ if (vma->vm_file)
+ atomic_add(2, &vma->vm_file->f_count);
+
+ if (vma->vm_ops && vma->vm_ops->open) {
+ vma->vm_ops->open(left);
+ vma->vm_ops->open(right);
+ }
+ vmlist_modify_lock(vma->vm_mm);
+ vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
+ vma->vm_start = start;
+ vma->vm_end = end;
+ setup_read_behavior(vma, behavior);
+ vma->vm_raend = 0;
+ insert_vm_struct(current->mm, left);
+ insert_vm_struct(current->mm, right);
+ vmlist_modify_unlock(vma->vm_mm);
+ return 0;
+}
+
+/*
+ * We can potentially split a vm area into separate
+ * areas, each area with its own behavior.
+ */
+static long madvise_behavior(struct vm_area_struct * vma,
+ unsigned long start, unsigned long end, int behavior)
+{
+ int error = 0;
+
+ /* Setting page-in behavior doesn't make sense for anonymous maps */
+ if (!vma->vm_file)
+ return -EBADF;
+
+ /* This caps the number of vma's this process can own */
+ if (vma->vm_mm->map_count > MAX_MAP_COUNT)
+ return -ENOMEM;
+
+ if (start == vma->vm_start) {
+ if (end == vma->vm_end) {
+ setup_read_behavior(vma, behavior);
+ vma->vm_raend = 0;
+ } else
+ error = madvise_fixup_start(vma, end, behavior);
+ } else {
+ if (end == vma->vm_end)
+ error = madvise_fixup_end(vma, start, behavior);
+ else
+ error = madvise_fixup_middle(vma, start, end, behavior);
+ }
+
+ return error;
+}
+
+/*
+ * Schedule all required I/O operations, then run the disk queue
+ * to make sure they are started. Do not wait for completion.
+ */
+long madvise_willneed(struct vm_area_struct * vma, unsigned long start,
+ unsigned long end)
+{
+ int error = 0;
+ unsigned long filesize;
+
+ /* Forcing page-ins doesn't make sense for anonymous maps */
+ if ((!vma->vm_file) || (!vma->vm_ops) || (!vma->vm_ops->nopage))
+ return -EBADF;
+
+ /* Convert start and end to page-size offsets into the file */
+ start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+ if (end > vma->vm_end)
+ end = vma->vm_end;
+ end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+ /* round to cluster boundaries if this isn't a "random" area */
+ filesize = filesize_in_pages(vma->vm_file);
+ if (!VM_RandomReadHint(vma)) {
+ start = CLUSTER_OFFSET(start);
+ end = CLUSTER_OFFSET(end + CLUSTER_PAGES - 1);
+
+ while ((start < end) && (start < filesize)) {
+ error = read_cluster_nonblocking(vma->vm_file, start,
+ filesize);
+ start += CLUSTER_PAGES;
+ if (error < 0)
+ break;
+ }
+ } else {
+ while ((start < end) && (start < filesize)) {
+ error = page_cache_read(vma->vm_file, start);
+ start++;
+ if (error < 0)
+ break;
+ }
+ }
+
+ run_task_queue(&tq_disk);
+ return error;
+}
+
+/*
+ * Application no longer needs these pages. If the pages are dirty,
+ * it's OK to just throw them away. The app will be more careful about
+ * data it wants to keep. Be sure to free swap resources too. The
+ * zap_page_range call sets things up for shrink_mmap to actually free
+ * these pages later if no one else has touched them in the meantime.
+ *
+ * NB: This interface discards data rather than pushes it out to swap,
+ * as some implementations do. This has performance implications for
+ * applications like large transactional databases which want to discard
+ * pages in anonymous maps after committing to backing store the data
+ * that was kept in them. There is no reason to write this data out to
+ * the swap area if the application is discarding it.
+ */
+long madvise_dontneed(struct vm_area_struct * vma, unsigned long start,
+ unsigned long end)
+{
+ if (vma->vm_flags & VM_LOCKED)
+ return -EINVAL;
+
+ lock_kernel();
+
+ flush_cache_range(vma->vm_mm, start, end);
+ zap_page_range(vma->vm_mm, start, end - start);
+ flush_tlb_range(vma->vm_mm, start, end);
+
+ unlock_kernel();
+ return 0;
+}
+
+static inline long madvise_area(struct vm_area_struct * vma,
+ unsigned long start, unsigned long end, int behavior)
+{
+ int error;
+
+ switch (behavior) {
+ case MADV_NORMAL:
+ case MADV_SEQUENTIAL:
+ case MADV_RANDOM:
+ error = madvise_behavior(vma, start, end, behavior);
+ break;
+
+ case MADV_WILLNEED:
+ error = madvise_willneed(vma, start, end);
+ break;
+
+ case MADV_DONTNEED:
+ error = madvise_dontneed(vma, start, end);
+ break;
+
+ default:
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior)
+{
+ unsigned long end;
+ struct vm_area_struct * vma;
+ int unmapped_error = 0;
+ int error = -EINVAL;
+
+ down(&current->mm->mmap_sem);
+
+ if (start & ~PAGE_MASK)
+ goto out;
+ len = (len + ~PAGE_MASK) & PAGE_MASK;
+ end = start + len;
+ if (end < start)
+ goto out;
+
+ error = 0;
+ if (end == start)
+ goto out;
+
+ /*
+ * If the interval [start,end) covers some unmapped address
+ * ranges, just ignore them, but return -ENOMEM at the end.
+ */
+ vma = find_vma(current->mm, start);
+ for (;;) {
+ /* Still start < end. */
+ error = -ENOMEM;
+ if (!vma)
+ goto out;
+
+ /* Here start < vma->vm_end. */
+ if (start < vma->vm_start) {
+ unmapped_error = -ENOMEM;
+ start = vma->vm_start;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end. */
+ if (end <= vma->vm_end) {
+ if (start < end) {
+ error = madvise_area(vma, start, end,
+ behavior);
+ if (error)
+ goto out;
+ }
+ error = unmapped_error;
+ goto out;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end < end. */
+ error = madvise_area(vma, start, vma->vm_end, behavior);
+ if (error)
+ goto out;
+ start = vma->vm_end;
+ vma = vma->vm_next;
+ }
+
+out:
+ up(&current->mm->mmap_sem);
+ return error;
+}
+
+/*
+ * The mincore(2) system call.
+ *
+ * mincore() returns the memory residency status of the pages in the
+ * current process's address space specified by [addr, addr + len).
+ * The status is returned in a vector of bytes. The least significant
+ * bit of each byte is 1 if the referenced page is in memory, otherwise
+ * it is zero.
+ *
+ * Because the status of a page can change after mincore() checks it
+ * but before it returns to the application, the returned vector may
+ * contain stale information. Only locked pages are guaranteed to
+ * remain in memory.
+ *
+ * return values:
+ * zero = success
+ * -1 = some error occurred, errno value set (see below).
+ *
+ * errno values:
+ * EFAULT - vec points to an illegal address
+ * EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
+ * or len has a nonpositive value
+ * ENOMEM - Addresses in the range [addr, addr + len] are
+ * invalid for the address space of this process, or
+ * specify one or more pages which are not currently
+ * mapped
+ */
+
+/*
+ * This predicate returns 1 if the page is "in core," otherwise 0.
+ *
+ * Later we can get more picky about what "in core" means precisely,
+ * but for now, it simply checks to see if the page is in the page
+ * cache, and is up to date; i.e. that no page-in operation would be
+ * required at this time if an application were to map and access
+ * this page.
+ *
+ * We are careful with locking here only to prevent an oops. The
+ * application already treats this information as a hint -- it can
+ * become stale by the time the app actually gets it.
+ */
+static inline char mincore_page_is_present(struct vm_area_struct * vma,
+ unsigned long pgoff)
+{
+ int result = 0;
+ struct inode * inode;
+ struct page * page, ** hash;
+
+ /* Anonymous pages are always present */
+ if (!vma->vm_file)
+ return 1;
+
+ inode = vma->vm_file->f_dentry->d_inode;
+ hash = page_hash(&inode->i_data, pgoff);
+ page = __find_get_page(&inode->i_data, pgoff, hash);
+ if (page) {
+ if (Page_Uptodate(page))
+ result = 1;
+ UnlockPage(page);
+ page_cache_release(page);
+ }
+
+ return result;
+}
+
+static long mincore_area(struct vm_area_struct * vma,
+ unsigned long start, unsigned long end, char * vec)
+{
+ int error, size, i = 0;
+ char * tmp;
+
+ start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+ if (end > vma->vm_end)
+ end = vma->vm_end;
+ end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+ /* # of bytes in "vec" = # of pages */
+ size = end - start;
+ tmp = (char *) vmalloc(size);
+ if (!tmp)
+ return -ENOMEM;
+
+ while (start < end)
+ tmp[i++] = mincore_page_is_present(vma, start++);
+
+ error = copy_to_user(vec, tmp, size) ? -EFAULT : 0;
+ vfree(tmp);
+ return error;
+}
+
+asmlinkage long sys_mincore(unsigned long start, size_t len, char *vec)
+{
+ int index = 0;
+ unsigned long end;
+ struct vm_area_struct * vma;
+ int unmapped_error = 0;
+ int error = -EINVAL;
+
+ down(&current->mm->mmap_sem);
+
+ if (start & ~PAGE_MASK)
+ goto out;
+ len = (len + ~PAGE_MASK) & PAGE_MASK;
+ end = start + len;
+ if (end < start)
+ goto out;
+
+ error = 0;
+ if (end == start)
+ goto out;
+
+ /*
+ * If the interval [start,end) covers some unmapped address
+ * ranges, just ignore them, but return -ENOMEM at the end.
+ */
+ vma = find_vma(current->mm, start);
+ for (;;) {
+ /* Still start < end. */
+ error = -ENOMEM;
+ if (!vma)
+ goto out;
+
+ /* Here start < vma->vm_end. */
+ if (start < vma->vm_start) {
+ unmapped_error = -ENOMEM;
+ start = vma->vm_start;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end. */
+ if (end <= vma->vm_end) {
+ if (start < end) {
+ error = mincore_area(vma, start, end,
+ &vec[index]);
+ if (error)
+ goto out;
+ }
+ error = unmapped_error;
+ goto out;
+ }
+
+ /* Here vma->vm_start <= start < vma->vm_end < end. */
+ error = mincore_area(vma, start, vma->vm_end, &vec[index]);
+ if (error)
+ goto out;
+ index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
+ start = vma->vm_end;
+ vma = vma->vm_next;
+ }
+
+out:
+ up(&current->mm->mmap_sem);
+ return error;
+}
+
#if 0
#define PROFILE_READAHEAD
#define DEBUG_READAHEAD
@@ -1291,6 +1792,61 @@
}

/*
+ * Read-ahead and flush behind for MADV_SEQUENTIAL areas. Since we are
+ * sure this is sequential access, we don't need a flexible read-ahead
+ * window size -- we can always use a large fixed size window.
+ */
+static void nopage_sequential_readahead(struct vm_area_struct * vma,
+ unsigned long pgoff, unsigned long filesize)
+{
+ unsigned long ra_window;
+
+ ra_window = get_max_readahead(vma->vm_file->f_dentry->d_inode);
+ ra_window = CLUSTER_OFFSET(ra_window + CLUSTER_PAGES - 1);
+
+ /* vm_raend is zero if we haven't read ahead in this area yet. */
+ if (vma->vm_raend == 0)
+ vma->vm_raend = vma->vm_pgoff + ra_window;
+
+ /*
+ * If we've just faulted the page half-way through our window,
+ * then schedule reads for the next window, and release the
+ * pages in the previous window.
+ */
+ if ((pgoff + (ra_window >> 1)) == vma->vm_raend) {
+ unsigned long start = vma->vm_pgoff + vma->vm_raend;
+ unsigned long end = start + ra_window;
+
+ if (end > ((vma->vm_end >> PAGE_SHIFT) + vma->vm_pgoff))
+ end = (vma->vm_end >> PAGE_SHIFT) + vma->vm_pgoff;
+ if (start > end)
+ return;
+
+ while ((start < end) && (start < filesize)) {
+ if (read_cluster_nonblocking(vma->vm_file,
+ start, filesize) < 0)
+ break;
+ start += CLUSTER_PAGES;
+ }
+ run_task_queue(&tq_disk);
+
+ /* if we're far enough past the beginning of this area,
+ recycle pages that are in the previous window. */
+ if (vma->vm_raend > (vma->vm_pgoff + ra_window + ra_window)) {
+ unsigned long window = ra_window << PAGE_SHIFT;
+
+ end = vma->vm_start + (vma->vm_raend << PAGE_SHIFT);
+ end -= window + window;
+ madvise_dontneed(vma, end - window, end);
+ }
+
+ vma->vm_raend += ra_window;
+ }
+
+ return;
+}
+
+/*
* filemap_nopage() is invoked via the vma operations vector for a
* mapped memory region to read in file data during a page fault.
*
@@ -1306,7 +1862,7 @@
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
struct page *page, **hash, *old_page;
- unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ unsigned long size = filesize_in_pages(file);

unsigned long pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;

@@ -1337,6 +1893,12 @@
goto page_not_uptodate;

success:
+ /*
+ * Try read-ahead for sequential areas.
+ */
+ if (VM_SequentialReadHint(area))
+ nopage_sequential_readahead(area, pgoff, size);
+
/*
* Found the page and have a reference on it, need to check sharing
* and possibly copy it over to another page..
@@ -1365,8 +1927,8 @@
* Otherwise, we're off the end of a privately mapped file,
* so we need to map a zero page.
*/
- if (pgoff < size)
- error = read_cluster_nonblocking(file, pgoff);
+ if ((pgoff < size ) && !VM_RandomReadHint(area))
+ error = read_cluster_nonblocking(file, pgoff, size);
else
error = page_cache_read(file, pgoff);

diff -ruN linux-ref/mm/mlock.c linux/mm/mlock.c
--- linux-ref/mm/mlock.c Thu Nov 4 16:04:06 1999
+++ linux/mm/mlock.c Tue Dec 21 16:03:35 1999
@@ -31,6 +31,7 @@
*n = *vma;
n->vm_end = end;
n->vm_flags = newflags;
+ n->vm_raend = 0;
if (n->vm_file)
get_file(n->vm_file);
if (n->vm_ops && n->vm_ops->open)
@@ -55,6 +56,7 @@
n->vm_start = start;
n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
n->vm_flags = newflags;
+ n->vm_raend = 0;
if (n->vm_file)
get_file(n->vm_file);
if (n->vm_ops && n->vm_ops->open)
@@ -85,6 +87,8 @@
right->vm_start = end;
right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
vma->vm_flags = newflags;
+ left->vm_raend = 0;
+ right->vm_raend = 0;
if (vma->vm_file)
atomic_add(2, &vma->vm_file->f_count);

@@ -97,6 +101,7 @@
vma->vm_start = start;
vma->vm_end = end;
vma->vm_flags = newflags;
+ vma->vm_raend = 0;
insert_vm_struct(current->mm, left);
insert_vm_struct(current->mm, right);
vmlist_modify_unlock(vma->vm_mm);
diff -ruN linux-ref/mm/mmap.c linux/mm/mmap.c
--- linux-ref/mm/mmap.c Tue Dec 21 13:59:00 1999
+++ linux/mm/mmap.c Tue Dec 21 16:03:35 1999
@@ -248,6 +248,9 @@
vma->vm_flags = vm_flags(prot,flags) | mm->def_flags;

if (file) {
+ VM_ClearReadHint(vma);
+ vma->vm_raend = 0;
+
if (file->f_mode & 1)
vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
if (flags & MAP_SHARED) {
@@ -544,6 +547,7 @@
mpnt->vm_end = area->vm_end;
mpnt->vm_page_prot = area->vm_page_prot;
mpnt->vm_flags = area->vm_flags;
+ mpnt->vm_raend = 0;
mpnt->vm_ops = area->vm_ops;
mpnt->vm_pgoff = area->vm_pgoff + ((end - area->vm_start) >> PAGE_SHIFT);
mpnt->vm_file = area->vm_file;
diff -ruN linux-ref/mm/mprotect.c linux/mm/mprotect.c
--- linux-ref/mm/mprotect.c Wed Nov 24 16:47:44 1999
+++ linux/mm/mprotect.c Tue Dec 21 16:03:35 1999
@@ -105,6 +105,7 @@
*n = *vma;
n->vm_end = end;
n->vm_flags = newflags;
+ n->vm_raend = 0;
n->vm_page_prot = prot;
if (n->vm_file)
get_file(n->vm_file);
@@ -131,6 +132,7 @@
n->vm_start = start;
n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
n->vm_flags = newflags;
+ n->vm_raend = 0;
n->vm_page_prot = prot;
if (n->vm_file)
get_file(n->vm_file);
@@ -162,6 +164,8 @@
left->vm_end = start;
right->vm_start = end;
right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
+ left->vm_raend = 0;
+ right->vm_raend = 0;
if (vma->vm_file)
atomic_add(2,&vma->vm_file->f_count);
if (vma->vm_ops && vma->vm_ops->open) {
@@ -173,6 +177,7 @@
vma->vm_start = start;
vma->vm_end = end;
vma->vm_flags = newflags;
+ vma->vm_raend = 0;
vma->vm_page_prot = prot;
insert_vm_struct(current->mm, left);
insert_vm_struct(current->mm, right);
diff -ruN linux-ref/mm/mremap.c linux/mm/mremap.c
--- linux-ref/mm/mremap.c Thu Dec 16 16:29:38 1999
+++ linux/mm/mremap.c Tue Dec 21 16:03:35 1999
@@ -135,8 +135,8 @@
*new_vma = *vma;
new_vma->vm_start = new_addr;
new_vma->vm_end = new_addr+new_len;
- new_vma->vm_pgoff = vma->vm_pgoff;
new_vma->vm_pgoff += (addr - vma->vm_start) >> PAGE_SHIFT;
+ new_vma->vm_raend = 0;
if (new_vma->vm_file)
get_file(new_vma->vm_file);
if (new_vma->vm_ops && new_vma->vm_ops->open)

- Chuck Lever

--
corporate:	<chuckl@netscape.com>
personal:	<chucklever@netscape.net> or <cel@monkey.org>

The Linux Scalability project: http://www.citi.umich.edu/projects/linux-scalability/

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/