Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757927AbXKKTuQ (ORCPT ); Sun, 11 Nov 2007 14:50:16 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756361AbXKKTuA (ORCPT ); Sun, 11 Nov 2007 14:50:00 -0500 Received: from pentafluge.infradead.org ([213.146.154.40]:35176 "EHLO pentafluge.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756296AbXKKTt5 (ORCPT ); Sun, 11 Nov 2007 14:49:57 -0500 Subject: Re: dio_get_page() lockdep complaints From: Peter Zijlstra To: Trond Myklebust Cc: Zach Brown , Jens Axboe , linux-kernel@vger.kernel.org, akpm@linux-foundation.org, linux-aio@kvack.org, Chris Mason , linux-mm , Hugh Dickins , Linus Torvalds , Martin Schwidefsky In-Reply-To: <1194630300.7459.65.camel@heimdal.trondhjem.org> References: <20070419073828.GB20928@kernel.dk> <1194627742.6289.175.camel@twins> <4734992C.7000408@oracle.com> <1194630300.7459.65.camel@heimdal.trondhjem.org> Content-Type: text/plain Date: Sun, 11 Nov 2007 20:49:06 +0100 Message-Id: <1194810546.6098.6.camel@lappy> Mime-Version: 1.0 X-Mailer: Evolution 2.12.0 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 46855 Lines: 1316 On Fri, 2007-11-09 at 12:45 -0500, Trond Myklebust wrote: > On Fri, 2007-11-09 at 09:30 -0800, Zach Brown wrote: > > So, reiserfs and NFS are nesting i_mutex inside the mmap_sem. > > > > >> [] mutex_lock+0x1c/0x1f > > >> [] reiserfs_file_release+0x54/0x447 > > >> [] __fput+0x53/0x101 > > >> [] fput+0x19/0x1c > > >> [] remove_vma+0x3b/0x4d > > >> [] do_munmap+0x17f/0x1cf > > > > > [] _mutex_lock+0x28/0x34 > > > [] nfs_revalidate_mapping+0x6d/0xac [nfs] > > > [] nfs_file_mmap+0x5c/0x74 [nfs] > > > [] do_mmap_pgoff+0x51a/0x817 > > > [] sys_mmap+0x90/0x119 > > > > I think i_mutex is fundamentally nested outside of the mmap_sem because > > of faulting in the buffered write path. I think these warnings could be > > reproduced with a careful test app which tries buffered writes from an > > address which will fault. > > > > DIO just tripped it up because it *always* performs get_user_pages() on > > the memory. > > > > So reiser and NFS need to be fixed. No? > > Actually, it is rather mmap() needs to be fixed. It is cold calling the > filesystem while holding all sorts of nasty locks. It needs to be > migrated to the same sort of syscall layout as read() and write(). > > You _first_ call the filesystem so that it can make whatever > preparations it needs outside the lock. The filesystem then calls the > VM, which can then call the filesystem back if needed. Right, which gets us into all kinds of trouble because some sites need mmap_sem to resolve some races, notably s390 31-bit and shm. Quick proto-type that moves mmap_sem into do_mmap{,_pgoff} and provides _locked functions for those few icky sites. The !_locked functions also call f_op->mmap_prepare() before taking the mmap_sem. Which makes for some ugly asymetry :-/ Anyway, I'm not comming up with anything nicer atm, hopefully a nice idea will present itself soon. (compile tested only - mostly for illustrational purposes) Not-signed-off-by: Peter Zijlstra --- arch/alpha/kernel/osf_sys.c | 2 - arch/arm/kernel/sys_arm.c | 2 - arch/avr32/kernel/sys_avr32.c | 2 - arch/blackfin/kernel/sys_bfin.c | 2 - arch/cris/kernel/sys_cris.c | 2 - arch/frv/kernel/sys_frv.c | 4 -- arch/h8300/kernel/sys_h8300.c | 4 -- arch/ia64/ia32/sys_ia32.c | 30 +++++----------- arch/ia64/kernel/sys_ia64.c | 2 - arch/m32r/kernel/sys_m32r.c | 2 - arch/m68k/kernel/sys_m68k.c | 4 -- arch/m68knommu/kernel/sys_m68k.c | 2 - arch/mips/kernel/irixelf.c | 10 ----- arch/mips/kernel/linux32.c | 2 - arch/mips/kernel/syscall.c | 2 - arch/mips/kernel/sysirix.c | 5 -- arch/parisc/kernel/sys_parisc.c | 2 - arch/powerpc/kernel/syscalls.c | 2 - arch/s390/kernel/compat_linux.c | 5 +- arch/s390/kernel/sys_s390.c | 2 - arch/sh/kernel/sys_sh.c | 2 - arch/sh64/kernel/sys_sh64.c | 2 - arch/sparc/kernel/sys_sparc.c | 2 - arch/sparc/kernel/sys_sunos.c | 2 - arch/sparc64/kernel/binfmt_aout32.c | 6 --- arch/sparc64/kernel/sys_sparc.c | 2 - arch/sparc64/kernel/sys_sunos32.c | 2 - arch/sparc64/solaris/misc.c | 2 - arch/um/kernel/syscall.c | 2 - arch/v850/kernel/syscalls.c | 2 - arch/x86/ia32/ia32_aout.c | 6 --- arch/x86/ia32/sys_ia32.c | 5 -- arch/x86/kernel/sys_i386_32.c | 2 - arch/x86/kernel/sys_x86_64.c | 2 - arch/xtensa/kernel/syscall.c | 2 - drivers/char/drm/drm_bufs.c | 4 -- drivers/char/drm/i810_dma.c | 2 - fs/aio.c | 4 +- fs/binfmt_aout.c | 6 --- fs/binfmt_elf.c | 6 --- fs/binfmt_elf_fdpic.c | 9 ---- fs/binfmt_flat.c | 6 +-- fs/binfmt_som.c | 6 --- fs/nfs/file.c | 25 +++++++++---- include/linux/fs.h | 1 include/linux/mm.h | 13 ++++++- ipc/shm.c | 2 - mm/mmap.c | 65 +++++++++++++++++++++++++++++++++--- 48 files changed, 109 insertions(+), 169 deletions(-) Index: linux-2.6-2/arch/alpha/kernel/osf_sys.c =================================================================== --- linux-2.6-2.orig/arch/alpha/kernel/osf_sys.c +++ linux-2.6-2/arch/alpha/kernel/osf_sys.c @@ -193,9 +193,7 @@ osf_mmap(unsigned long addr, unsigned lo goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); ret = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); if (file) fput(file); out: Index: linux-2.6-2/arch/arm/kernel/sys_arm.c =================================================================== --- linux-2.6-2.orig/arch/arm/kernel/sys_arm.c +++ linux-2.6-2/arch/arm/kernel/sys_arm.c @@ -72,9 +72,7 @@ inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/avr32/kernel/sys_avr32.c =================================================================== --- linux-2.6-2.orig/arch/avr32/kernel/sys_avr32.c +++ linux-2.6-2/arch/avr32/kernel/sys_avr32.c @@ -41,9 +41,7 @@ asmlinkage long sys_mmap2(unsigned long return error; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, offset); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/blackfin/kernel/sys_bfin.c =================================================================== --- linux-2.6-2.orig/arch/blackfin/kernel/sys_bfin.c +++ linux-2.6-2/arch/blackfin/kernel/sys_bfin.c @@ -78,9 +78,7 @@ do_mmap2(unsigned long addr, unsigned lo goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/cris/kernel/sys_cris.c =================================================================== --- linux-2.6-2.orig/arch/cris/kernel/sys_cris.c +++ linux-2.6-2/arch/cris/kernel/sys_cris.c @@ -60,9 +60,7 @@ do_mmap2(unsigned long addr, unsigned lo goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/frv/kernel/sys_frv.c =================================================================== --- linux-2.6-2.orig/arch/frv/kernel/sys_frv.c +++ linux-2.6-2/arch/frv/kernel/sys_frv.c @@ -69,9 +69,7 @@ asmlinkage long sys_mmap2(unsigned long pgoff >>= (PAGE_SHIFT - 12); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); @@ -114,9 +112,7 @@ asmlinkage long sys_mmap64(struct mmap_a } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); out: Index: linux-2.6-2/arch/h8300/kernel/sys_h8300.c =================================================================== --- linux-2.6-2.orig/arch/h8300/kernel/sys_h8300.c +++ linux-2.6-2/arch/h8300/kernel/sys_h8300.c @@ -60,9 +60,7 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); @@ -147,9 +145,7 @@ asmlinkage long sys_mmap64(struct mmap_a } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); out: Index: linux-2.6-2/arch/ia64/ia32/sys_ia32.c =================================================================== --- linux-2.6-2.orig/arch/ia64/ia32/sys_ia32.c +++ linux-2.6-2/arch/ia64/ia32/sys_ia32.c @@ -212,12 +212,8 @@ mmap_subpage (struct file *file, unsigne if (old_prot) copy_from_user(page, (void __user *) PAGE_START(start), PAGE_SIZE); - down_write(¤t->mm->mmap_sem); - { - ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE, - flags | MAP_FIXED | MAP_ANONYMOUS, 0); - } - up_write(¤t->mm->mmap_sem); + ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE, + flags | MAP_FIXED | MAP_ANONYMOUS, 0); if (IS_ERR((void *) ret)) goto out; @@ -821,16 +817,14 @@ emulate_mmap (struct file *file, unsigne DBG("mmap_body: mapping [0x%lx-0x%lx) %s with poff 0x%llx\n", pstart, pend, is_congruent ? "congruent" : "not congruent", poff); - down_write(¤t->mm->mmap_sem); - { - if (!(flags & MAP_ANONYMOUS) && is_congruent) - ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff); - else - ret = do_mmap(NULL, pstart, pend - pstart, - prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE), - flags | MAP_FIXED | MAP_ANONYMOUS, 0); + if (!(flags & MAP_ANONYMOUS) && is_congruent) { + ret = do_mmap(file, pstart, pend - pstart, prot, + flags | MAP_FIXED, poff); + } else { + ret = do_mmap(NULL, pstart, pend - pstart, + prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE), + flags | MAP_FIXED | MAP_ANONYMOUS, 0); } - up_write(¤t->mm->mmap_sem); if (IS_ERR((void *) ret)) return ret; @@ -904,11 +898,7 @@ ia32_do_mmap (struct file *file, unsigne } mutex_unlock(&ia32_mmap_mutex); #else - down_write(¤t->mm->mmap_sem); - { - addr = do_mmap(file, addr, len, prot, flags, offset); - } - up_write(¤t->mm->mmap_sem); + addr = do_mmap(file, addr, len, prot, flags, offset); #endif DBG("ia32_do_mmap: returning 0x%lx\n", addr); return addr; Index: linux-2.6-2/arch/ia64/kernel/sys_ia64.c =================================================================== --- linux-2.6-2.orig/arch/ia64/kernel/sys_ia64.c +++ linux-2.6-2/arch/ia64/kernel/sys_ia64.c @@ -209,9 +209,7 @@ do_mmap2 (unsigned long addr, unsigned l goto out; } - down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); out: if (file) fput(file); Index: linux-2.6-2/arch/m32r/kernel/sys_m32r.c =================================================================== --- linux-2.6-2.orig/arch/m32r/kernel/sys_m32r.c +++ linux-2.6-2/arch/m32r/kernel/sys_m32r.c @@ -110,9 +110,7 @@ asmlinkage long sys_mmap2(unsigned long goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/m68k/kernel/sys_m68k.c =================================================================== --- linux-2.6-2.orig/arch/m68k/kernel/sys_m68k.c +++ linux-2.6-2/arch/m68k/kernel/sys_m68k.c @@ -63,9 +63,7 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); @@ -150,9 +148,7 @@ asmlinkage long sys_mmap64(struct mmap_a } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); out: Index: linux-2.6-2/arch/m68knommu/kernel/sys_m68k.c =================================================================== --- linux-2.6-2.orig/arch/m68knommu/kernel/sys_m68k.c +++ linux-2.6-2/arch/m68knommu/kernel/sys_m68k.c @@ -61,9 +61,7 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/mips/kernel/irixelf.c =================================================================== --- linux-2.6-2.orig/arch/mips/kernel/irixelf.c +++ linux-2.6-2/arch/mips/kernel/irixelf.c @@ -342,12 +342,10 @@ static unsigned int load_irix_interp(str (unsigned long) (eppnt->p_offset & 0xfffff000)); - down_write(¤t->mm->mmap_sem); error = do_mmap(interpreter, vaddr, eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), elf_prot, elf_type, eppnt->p_offset & 0xfffff000); - up_write(¤t->mm->mmap_sem); if (error < 0 && error > -1024) { printk("Aieee IRIX interp mmap error=%d\n", @@ -514,12 +512,10 @@ static inline void map_executable(struct prot = (epp->p_flags & PF_R) ? PROT_READ : 0; prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0; prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0; - down_write(¤t->mm->mmap_sem); (void) do_mmap(fp, (epp->p_vaddr & 0xfffff000), (epp->p_filesz + (epp->p_vaddr & 0xfff)), prot, EXEC_MAP_FLAGS, (epp->p_offset & 0xfffff000)); - up_write(¤t->mm->mmap_sem); /* Fixup location tracking vars. */ if ((epp->p_vaddr & 0xfffff000) < *estack) @@ -798,10 +794,8 @@ static int load_irix_binary(struct linux * Since we do not have the power to recompile these, we * emulate the SVr4 behavior. Sigh. */ - down_write(¤t->mm->mmap_sem); (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); #endif start_thread(regs, elf_entry, bprm->p); @@ -871,14 +865,12 @@ static int load_irix_library(struct file while (elf_phdata->p_type != PT_LOAD) elf_phdata++; /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(file, elf_phdata->p_vaddr & 0xfffff000, elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, elf_phdata->p_offset & 0xfffff000); - up_write(¤t->mm->mmap_sem); k = elf_phdata->p_vaddr + elf_phdata->p_filesz; if (k > elf_bss) elf_bss = k; @@ -959,12 +951,10 @@ unsigned long irix_mapelf(int fd, struct prot |= (flags & PF_W) ? PROT_WRITE : 0; prot |= (flags & PF_X) ? PROT_EXEC : 0; - down_write(¤t->mm->mmap_sem); retval = do_mmap(filp, (vaddr & 0xfffff000), (filesz + (vaddr & 0xfff)), prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), (offset & 0xfffff000)); - up_write(¤t->mm->mmap_sem); if (retval != (vaddr & 0xfffff000)) { printk("irix_mapelf: do_mmap fails with %d!\n", retval); Index: linux-2.6-2/arch/mips/kernel/linux32.c =================================================================== --- linux-2.6-2.orig/arch/mips/kernel/linux32.c +++ linux-2.6-2/arch/mips/kernel/linux32.c @@ -119,9 +119,7 @@ sys32_mmap2(unsigned long addr, unsigned } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/mips/kernel/syscall.c =================================================================== --- linux-2.6-2.orig/arch/mips/kernel/syscall.c +++ linux-2.6-2/arch/mips/kernel/syscall.c @@ -136,9 +136,7 @@ do_mmap2(unsigned long addr, unsigned lo goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/mips/kernel/sysirix.c =================================================================== --- linux-2.6-2.orig/arch/mips/kernel/sysirix.c +++ linux-2.6-2/arch/mips/kernel/sysirix.c @@ -1051,9 +1051,7 @@ asmlinkage unsigned long irix_mmap32(uns flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, offset); - up_write(¤t->mm->mmap_sem); if (file) fput(file); @@ -1536,10 +1534,7 @@ asmlinkage int irix_mmap64(struct pt_reg flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) fput(file); Index: linux-2.6-2/arch/parisc/kernel/sys_parisc.c =================================================================== --- linux-2.6-2.orig/arch/parisc/kernel/sys_parisc.c +++ linux-2.6-2/arch/parisc/kernel/sys_parisc.c @@ -137,9 +137,7 @@ static unsigned long do_mmap2(unsigned l flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file != NULL) fput(file); Index: linux-2.6-2/arch/powerpc/kernel/syscalls.c =================================================================== --- linux-2.6-2.orig/arch/powerpc/kernel/syscalls.c +++ linux-2.6-2/arch/powerpc/kernel/syscalls.c @@ -175,9 +175,7 @@ static inline unsigned long do_mmap2(uns flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); ret = do_mmap_pgoff(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); if (file) fput(file); out: Index: linux-2.6-2/arch/s390/kernel/compat_linux.c =================================================================== --- linux-2.6-2.orig/arch/s390/kernel/compat_linux.c +++ linux-2.6-2/arch/s390/kernel/compat_linux.c @@ -860,14 +860,15 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { /* Result is out of bounds. */ + /* XXX fix race - APZ */ + down_write(¤t->mm->mmap_sem); do_munmap(current->mm, addr, len); + up_write(¤t->mm->mmap_sem); error = -ENOMEM; } - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/s390/kernel/sys_s390.c =================================================================== --- linux-2.6-2.orig/arch/s390/kernel/sys_s390.c +++ linux-2.6-2/arch/s390/kernel/sys_s390.c @@ -65,9 +65,7 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/sh/kernel/sys_sh.c =================================================================== --- linux-2.6-2.orig/arch/sh/kernel/sys_sh.c +++ linux-2.6-2/arch/sh/kernel/sys_sh.c @@ -153,9 +153,7 @@ do_mmap2(unsigned long addr, unsigned lo goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/sh64/kernel/sys_sh64.c =================================================================== --- linux-2.6-2.orig/arch/sh64/kernel/sys_sh64.c +++ linux-2.6-2/arch/sh64/kernel/sys_sh64.c @@ -148,9 +148,7 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/sparc/kernel/sys_sparc.c =================================================================== --- linux-2.6-2.orig/arch/sparc/kernel/sys_sparc.c +++ linux-2.6-2/arch/sparc/kernel/sys_sparc.c @@ -252,9 +252,7 @@ static unsigned long do_mmap2(unsigned l len = PAGE_ALIGN(len); flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/sparc/kernel/sys_sunos.c =================================================================== --- linux-2.6-2.orig/arch/sparc/kernel/sys_sunos.c +++ linux-2.6-2/arch/sparc/kernel/sys_sunos.c @@ -120,9 +120,7 @@ asmlinkage unsigned long sunos_mmap(unsi } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); if (!ret_type) retval = ((retval < PAGE_OFFSET) ? 0 : retval); Index: linux-2.6-2/arch/sparc64/kernel/binfmt_aout32.c =================================================================== --- linux-2.6-2.orig/arch/sparc64/kernel/binfmt_aout32.c +++ linux-2.6-2/arch/sparc64/kernel/binfmt_aout32.c @@ -290,24 +290,20 @@ static int load_aout32_binary(struct lin goto beyond_if; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); - up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; @@ -379,12 +375,10 @@ static int load_aout32_library(struct fi start_addr = ex.a_entry & 0xfffff000; /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; Index: linux-2.6-2/arch/sparc64/kernel/sys_sparc.c =================================================================== --- linux-2.6-2.orig/arch/sparc64/kernel/sys_sparc.c +++ linux-2.6-2/arch/sparc64/kernel/sys_sparc.c @@ -576,9 +576,7 @@ asmlinkage unsigned long sys_mmap(unsign flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); len = PAGE_ALIGN(len); - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/sparc64/kernel/sys_sunos32.c =================================================================== --- linux-2.6-2.orig/arch/sparc64/kernel/sys_sunos32.c +++ linux-2.6-2/arch/sparc64/kernel/sys_sunos32.c @@ -99,12 +99,10 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 flags &= ~_MAP_NEW; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, (unsigned long) addr, (unsigned long) len, (unsigned long) prot, (unsigned long) flags, (unsigned long) off); - up_write(¤t->mm->mmap_sem); if (!ret_type) retval = ((retval < 0xf0000000) ? 0 : retval); out_putf: Index: linux-2.6-2/arch/sparc64/solaris/misc.c =================================================================== --- linux-2.6-2.orig/arch/sparc64/solaris/misc.c +++ linux-2.6-2/arch/sparc64/solaris/misc.c @@ -95,12 +95,10 @@ static u32 do_solaris_mmap(u32 addr, u32 ret_type = flags & _MAP_NEW; flags &= ~_MAP_NEW; - down_write(¤t->mm->mmap_sem); flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, (unsigned long) addr, (unsigned long) len, (unsigned long) prot, (unsigned long) flags, off); - up_write(¤t->mm->mmap_sem); if(!ret_type) retval = ((retval < STACK_TOP32) ? 0 : retval); Index: linux-2.6-2/arch/um/kernel/syscall.c =================================================================== --- linux-2.6-2.orig/arch/um/kernel/syscall.c +++ linux-2.6-2/arch/um/kernel/syscall.c @@ -54,9 +54,7 @@ long sys_mmap2(unsigned long addr, unsig goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/v850/kernel/syscalls.c =================================================================== --- linux-2.6-2.orig/arch/v850/kernel/syscalls.c +++ linux-2.6-2/arch/v850/kernel/syscalls.c @@ -164,9 +164,7 @@ do_mmap2 (unsigned long addr, size_t len goto out; } - down_write (¤t->mm->mmap_sem); ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff); - up_write (¤t->mm->mmap_sem); if (file) fput (file); out: Index: linux-2.6-2/arch/x86/ia32/ia32_aout.c =================================================================== --- linux-2.6-2.orig/arch/x86/ia32/ia32_aout.c +++ linux-2.6-2/arch/x86/ia32/ia32_aout.c @@ -374,24 +374,20 @@ static int load_aout_binary(struct linux goto beyond_if; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, fd_offset); - up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; @@ -488,12 +484,10 @@ static int load_aout_library(struct file goto out; } /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT, N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; Index: linux-2.6-2/arch/x86/ia32/sys_ia32.c =================================================================== --- linux-2.6-2.orig/arch/x86/ia32/sys_ia32.c +++ linux-2.6-2/arch/x86/ia32/sys_ia32.c @@ -242,13 +242,10 @@ sys32_mmap(struct mmap_arg_struct __user } mm = current->mm; - down_write(&mm->mmap_sem); retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT); if (file) fput(file); - up_write(&mm->mmap_sem); - return retval; } @@ -708,9 +705,7 @@ asmlinkage long sys32_mmap2(unsigned lon return -EBADF; } - down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/x86/kernel/sys_i386_32.c =================================================================== --- linux-2.6-2.orig/arch/x86/kernel/sys_i386_32.c +++ linux-2.6-2/arch/x86/kernel/sys_i386_32.c @@ -54,9 +54,7 @@ asmlinkage long sys_mmap2(unsigned long goto out; } - down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/x86/kernel/sys_x86_64.c =================================================================== --- linux-2.6-2.orig/arch/x86/kernel/sys_x86_64.c +++ linux-2.6-2/arch/x86/kernel/sys_x86_64.c @@ -51,9 +51,7 @@ asmlinkage long sys_mmap(unsigned long a if (!file) goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/arch/xtensa/kernel/syscall.c =================================================================== --- linux-2.6-2.orig/arch/xtensa/kernel/syscall.c +++ linux-2.6-2/arch/xtensa/kernel/syscall.c @@ -72,9 +72,7 @@ asmlinkage long xtensa_mmap2(unsigned lo goto out; } - down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); if (file) fput(file); Index: linux-2.6-2/drivers/char/drm/drm_bufs.c =================================================================== --- linux-2.6-2.orig/drivers/char/drm/drm_bufs.c +++ linux-2.6-2/drivers/char/drm/drm_bufs.c @@ -1517,18 +1517,14 @@ int drm_mapbufs(struct drm_device *dev, retcode = -EINVAL; goto done; } - down_write(¤t->mm->mmap_sem); virtual = do_mmap(file_priv->filp, 0, map->size, PROT_READ | PROT_WRITE, MAP_SHARED, token); - up_write(¤t->mm->mmap_sem); } else { - down_write(¤t->mm->mmap_sem); virtual = do_mmap(file_priv->filp, 0, dma->byte_count, PROT_READ | PROT_WRITE, MAP_SHARED, 0); - up_write(¤t->mm->mmap_sem); } if (virtual > -1024UL) { /* Real error */ Index: linux-2.6-2/drivers/char/drm/i810_dma.c =================================================================== --- linux-2.6-2.orig/drivers/char/drm/i810_dma.c +++ linux-2.6-2/drivers/char/drm/i810_dma.c @@ -131,7 +131,6 @@ static int i810_map_buffer(struct drm_bu if (buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL; - down_write(¤t->mm->mmap_sem); old_fops = file_priv->filp->f_op; file_priv->filp->f_op = &i810_buffer_fops; dev_priv->mmap_buffer = buf; @@ -146,7 +145,6 @@ static int i810_map_buffer(struct drm_bu retcode = PTR_ERR(buf_priv->virtual); buf_priv->virtual = NULL; } - up_write(¤t->mm->mmap_sem); return retcode; } Index: linux-2.6-2/fs/aio.c =================================================================== --- linux-2.6-2.orig/fs/aio.c +++ linux-2.6-2/fs/aio.c @@ -129,18 +129,18 @@ static int aio_setup_ring(struct kioctx info->mmap_size = nr_pages * PAGE_SIZE; dprintk("attempting mmap of %lu bytes\n", info->mmap_size); - down_write(&ctx->mm->mmap_sem); + WARN_ON(ctx->mm != current->mm); info->mmap_base = do_mmap(NULL, 0, info->mmap_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0); if (IS_ERR((void *)info->mmap_base)) { - up_write(&ctx->mm->mmap_sem); info->mmap_size = 0; aio_free_ring(ctx); return -EAGAIN; } dprintk("mmap address: 0x%08lx\n", info->mmap_base); + down_write(&ctx->mm->mmap_sem); info->nr_pages = get_user_pages(current, ctx->mm, info->mmap_base, nr_pages, 1, 0, info->ring_pages, NULL); Index: linux-2.6-2/fs/binfmt_aout.c =================================================================== --- linux-2.6-2.orig/fs/binfmt_aout.c +++ linux-2.6-2/fs/binfmt_aout.c @@ -403,24 +403,20 @@ static int load_aout_binary(struct linux goto beyond_if; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); - up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } - down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; @@ -518,12 +514,10 @@ static int load_aout_library(struct file goto out; } /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; Index: linux-2.6-2/fs/binfmt_elf.c =================================================================== --- linux-2.6-2.orig/fs/binfmt_elf.c +++ linux-2.6-2/fs/binfmt_elf.c @@ -303,7 +303,6 @@ static unsigned long elf_map(struct file unsigned long map_addr; unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); - down_write(¤t->mm->mmap_sem); /* mmap() will return -EINVAL if given a zero size, but a * segment with zero filesize is perfectly valid */ if (eppnt->p_filesz + pageoffset) @@ -312,7 +311,6 @@ static unsigned long elf_map(struct file eppnt->p_offset - pageoffset); else map_addr = ELF_PAGESTART(addr); - up_write(¤t->mm->mmap_sem); return(map_addr); } @@ -1026,10 +1024,8 @@ static int load_elf_binary(struct linux_ and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we emulate the SVr4 behavior. Sigh. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); } #ifdef ELF_PLAT_INIT @@ -1125,7 +1121,6 @@ static int load_elf_library(struct file eppnt++; /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); error = do_mmap(file, ELF_PAGESTART(eppnt->p_vaddr), (eppnt->p_filesz + @@ -1134,7 +1129,6 @@ static int load_elf_library(struct file MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, (eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr))); - up_write(¤t->mm->mmap_sem); if (error != ELF_PAGESTART(eppnt->p_vaddr)) goto out_free_ph; Index: linux-2.6-2/fs/binfmt_elf_fdpic.c =================================================================== --- linux-2.6-2.orig/fs/binfmt_elf_fdpic.c +++ linux-2.6-2/fs/binfmt_elf_fdpic.c @@ -370,14 +370,12 @@ static int load_elf_fdpic_binary(struct if (stack_size < PAGE_SIZE * 2) stack_size = PAGE_SIZE * 2; - down_write(¤t->mm->mmap_sem); current->mm->start_brk = do_mmap(NULL, 0, stack_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, 0); if (IS_ERR_VALUE(current->mm->start_brk)) { - up_write(¤t->mm->mmap_sem); retval = current->mm->start_brk; current->mm->start_brk = 0; goto error_kill; @@ -385,6 +383,7 @@ static int load_elf_fdpic_binary(struct /* expand the stack mapping to use up the entire allocation granule */ fullsize = ksize((char *) current->mm->start_brk); + down_write(¤t->mm->mmap_sem); if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size, fullsize, 0, 0))) stack_size = fullsize; @@ -904,10 +903,8 @@ static int elf_fdpic_map_file_constdisp_ if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE) mflags |= MAP_EXECUTABLE; - down_write(&mm->mmap_sem); maddr = do_mmap(NULL, load_addr, top - base, PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); - up_write(&mm->mmap_sem); if (IS_ERR_VALUE(maddr)) return (int) maddr; @@ -1050,10 +1047,8 @@ static int elf_fdpic_map_file_by_direct_ /* create the mapping */ disp = phdr->p_vaddr & ~PAGE_MASK; - down_write(&mm->mmap_sem); maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp); - up_write(&mm->mmap_sem); kdebug("mmap[%d] sz=%lx pr=%x fl=%x of=%lx --> %08lx", loop, phdr->p_memsz + disp, prot, flags, @@ -1096,10 +1091,8 @@ static int elf_fdpic_map_file_by_direct_ unsigned long xmaddr; flags |= MAP_FIXED | MAP_ANONYMOUS; - down_write(&mm->mmap_sem); xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0); - up_write(&mm->mmap_sem); kdebug("mmap[%d] " " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", Index: linux-2.6-2/fs/binfmt_flat.c =================================================================== --- linux-2.6-2.orig/fs/binfmt_flat.c +++ linux-2.6-2/fs/binfmt_flat.c @@ -531,9 +531,7 @@ static int load_flat_file(struct linux_b */ DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); - down_write(¤t->mm->mmap_sem); textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos) textpos = (unsigned long) -ENOMEM; @@ -544,7 +542,7 @@ static int load_flat_file(struct linux_b len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); down_write(¤t->mm->mmap_sem); - realdatastart = do_mmap(0, 0, len, + realdatastart = do_mmap_locked(0, 0, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); /* Remap to use all availabe slack region space */ if (realdatastart && (realdatastart < (unsigned long)-4096)) { @@ -596,7 +594,7 @@ static int load_flat_file(struct linux_b len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); down_write(¤t->mm->mmap_sem); - textpos = do_mmap(0, 0, len, + textpos = do_mmap_locked(0, 0, len, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); /* Remap to use all availabe slack region space */ if (textpos && (textpos < (unsigned long) -4096)) { Index: linux-2.6-2/fs/binfmt_som.c =================================================================== --- linux-2.6-2.orig/fs/binfmt_som.c +++ linux-2.6-2/fs/binfmt_som.c @@ -148,10 +148,8 @@ static int map_som_binary(struct file *f code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); current->mm->start_code = code_start; current->mm->end_code = code_start + code_size; - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, code_start, code_size, prot, flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); - up_write(¤t->mm->mmap_sem); if (retval < 0 && retval > -1024) goto out; @@ -159,20 +157,16 @@ static int map_som_binary(struct file *f data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); current->mm->start_data = data_start; current->mm->end_data = bss_start = data_start + data_size; - down_write(¤t->mm->mmap_sem); retval = do_mmap(file, data_start, data_size, prot | PROT_WRITE, flags, SOM_PAGESTART(hpuxhdr->exec_dfile)); - up_write(¤t->mm->mmap_sem); if (retval < 0 && retval > -1024) goto out; som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); current->mm->start_brk = current->mm->brk = som_brk; - down_write(¤t->mm->mmap_sem); retval = do_mmap(NULL, bss_start, som_brk - bss_start, prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); - up_write(¤t->mm->mmap_sem); if (retval > 0 || retval < -1024) retval = 0; out: Index: linux-2.6-2/fs/nfs/file.c =================================================================== --- linux-2.6-2.orig/fs/nfs/file.c +++ linux-2.6-2/fs/nfs/file.c @@ -41,6 +41,9 @@ static int nfs_file_open(struct inode *, struct file *); static int nfs_file_release(struct inode *, struct file *); static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); +static int +nfs_file_mmap_prepare(struct file * file, unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long pgoff); static int nfs_file_mmap(struct file *, struct vm_area_struct *); static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, struct pipe_inode_info *pipe, @@ -64,6 +67,7 @@ const struct file_operations nfs_file_op .write = do_sync_write, .aio_read = nfs_file_read, .aio_write = nfs_file_write, + .mmap_prepare = nfs_file_mmap_prepare, .mmap = nfs_file_mmap, .open = nfs_file_open, .flush = nfs_file_flush, @@ -270,7 +274,8 @@ nfs_file_splice_read(struct file *filp, } static int -nfs_file_mmap(struct file * file, struct vm_area_struct * vma) +nfs_file_mmap_prepare(struct file * file, unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long pgoff) { struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; @@ -279,13 +284,17 @@ nfs_file_mmap(struct file * file, struct dfprintk(VFS, "nfs: mmap(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); - status = nfs_revalidate_mapping(inode, file->f_mapping); - if (!status) { - vma->vm_ops = &nfs_file_vm_ops; - vma->vm_flags |= VM_CAN_NONLINEAR; - file_accessed(file); - } - return status; + return nfs_revalidate_mapping(inode, file->f_mapping); +} + +static int +nfs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + vma->vm_ops = &nfs_file_vm_ops; + vma->vm_flags |= VM_CAN_NONLINEAR; + file_accessed(file); + + return 0; } /* Index: linux-2.6-2/include/linux/fs.h =================================================================== --- linux-2.6-2.orig/include/linux/fs.h +++ linux-2.6-2/include/linux/fs.h @@ -1172,6 +1172,7 @@ struct file_operations { int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap_prepare) (struct file *, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long pgoff); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); Index: linux-2.6-2/include/linux/mm.h =================================================================== --- linux-2.6-2.orig/include/linux/mm.h +++ linux-2.6-2/include/linux/mm.h @@ -980,6 +980,10 @@ extern int install_special_mapping(struc extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); +extern unsigned long do_mmap_pgoff_locked( + struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long pgoff); extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long pgoff); @@ -988,7 +992,7 @@ extern unsigned long mmap_region(struct unsigned int vm_flags, unsigned long pgoff, int accountable); -static inline unsigned long do_mmap(struct file *file, unsigned long addr, +static inline unsigned long do_mmap_locked(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset) { @@ -996,11 +1000,16 @@ static inline unsigned long do_mmap(stru if ((offset + PAGE_ALIGN(len)) < offset) goto out; if (!(offset & ~PAGE_MASK)) - ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); + ret = do_mmap_pgoff_locked(file, addr, len, prot, + flag, offset >> PAGE_SHIFT); out: return ret; } +extern unsigned long do_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long offset); + extern int do_munmap(struct mm_struct *, unsigned long, size_t); extern unsigned long do_brk(unsigned long, unsigned long); Index: linux-2.6-2/ipc/shm.c =================================================================== --- linux-2.6-2.orig/ipc/shm.c +++ linux-2.6-2/ipc/shm.c @@ -1012,7 +1012,7 @@ long do_shmat(int shmid, char __user *sh goto invalid; } - user_addr = do_mmap (file, addr, size, prot, flags, 0); + user_addr = do_mmap_locked (file, addr, size, prot, flags, 0); *raddr = user_addr; err = 0; if (IS_ERR_VALUE(user_addr)) Index: linux-2.6-2/mm/mmap.c =================================================================== --- linux-2.6-2.orig/mm/mmap.c +++ linux-2.6-2/mm/mmap.c @@ -888,9 +888,10 @@ void vm_stat_account(struct mm_struct *m * The caller must hold down_write(current->mm->mmap_sem). */ -unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flags, unsigned long pgoff) +static unsigned long __do_mmap_pgoff_locked( + struct file * file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long pgoff) { struct mm_struct * mm = current->mm; struct inode *inode; @@ -1026,10 +1027,66 @@ unsigned long do_mmap_pgoff(struct file return mmap_region(file, addr, len, flags, vm_flags, pgoff, accountable); } + +unsigned long do_mmap_pgoff_locked(struct file * file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long pgoff) +{ + WARN_ON(file && file->f_op->mmap_prepare); + return __do_mmap_pgoff_locked(file, addr, len, prot, flags, pgoff); +} +EXPORT_SYMBOL(do_mmap_pgoff_locked); + +unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long pgoff) +{ + struct mm_struct *mm = current->mm; + unsigned long ret; + + if (file && file->f_op->mmap_prepare) { + ret = file->f_op->mmap_prepare(file, addr, + len, prot, flags, pgoff); + if (ret) + return ret; + } + + down_write(&mm->mmap_sem); + ret = __do_mmap_pgoff_locked(file, addr, len, prot, flags, pgoff); + up_write(&mm->mmap_sem); + + return ret; +} EXPORT_SYMBOL(do_mmap_pgoff); +unsigned long do_mmap(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long offset) +{ + struct mm_struct *mm = current->mm; + unsigned long ret = -EINVAL; + unsigned long pgoff = offset >> PAGE_SHIFT; + + if ((offset + PAGE_ALIGN(len)) < offset || (offset & ~PAGE_MASK)) + return ret; + + if (file && file->f_op->mmap_prepare) { + ret = file->f_op->mmap_prepare(file, addr, + len, prot, flags, pgoff); + if (ret) + return ret; + } + + down_write(&mm->mmap_sem); + ret = __do_mmap_pgoff_locked(file, addr, len, prot, flags, pgoff); + up_write(&mm->mmap_sem); + + return ret; +} +EXPORT_SYMBOL(do_mmap); + /* - * Some shared mappigns will want the pages marked read-only + * Some shared mappings will want the pages marked read-only * to track write events. If so, we'll downgrade vm_page_prot * to the private version (using protection_map[] without the * VM_SHARED bit). - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/