linux/fs/nilfs2
Miklos Szeredi 2aa15890f3 mm: prevent concurrent unmap_mapping_range() on the same inode
Michael Leun reported that running parallel opens on a fuse filesystem
can trigger a "kernel BUG at mm/truncate.c:475"

Gurudas Pai reported the same bug on NFS.

The reason is, unmap_mapping_range() is not prepared for more than
one concurrent invocation per inode.  For example:

  thread1: going through a big range, stops in the middle of a vma and
     stores the restart address in vm_truncate_count.

  thread2: comes in with a small (e.g. single page) unmap request on
     the same vma, somewhere before restart_address, finds that the
     vma was already unmapped up to the restart address and happily
     returns without doing anything.

Another scenario would be two big unmap requests, both having to
restart the unmapping and each one setting vm_truncate_count to its
own value.  This could go on forever without any of them being able to
finish.

Truncate and hole punching already serialize with i_mutex.  Other
callers of unmap_mapping_range() do not, and it's difficult to get
i_mutex protection for all callers.  In particular ->d_revalidate(),
which calls invalidate_inode_pages2_range() in fuse, may be called
with or without i_mutex.

This patch adds a new mutex to 'struct address_space' to prevent
running multiple concurrent unmap_mapping_range() on the same mapping.

[ We'll hopefully get rid of all this with the upcoming mm
  preemptibility series by Peter Zijlstra, the "mm: Remove i_mmap_mutex
  lockbreak" patch in particular.  But that is for 2.6.39 ]

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reported-by: Michael Leun <lkml20101129@newton.leun.net>
Reported-by: Gurudas Pai <gurudas.pai@oracle.com>
Tested-by: Gurudas Pai <gurudas.pai@oracle.com>
Acked-by: Hugh Dickins <hughd@google.com>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-02-23 19:52:52 -08:00
..
Kconfig Revert "task_struct: make journal_info conditional" 2009-12-17 13:23:24 -08:00
Makefile nilfs2: get rid of GCDAT inode 2010-10-23 09:24:38 +09:00
alloc.c nilfs2: add kernel doc comments to persistent object allocator functions 2010-05-10 11:32:31 +09:00
alloc.h nilfs2: add kernel doc comments to persistent object allocator functions 2010-05-10 11:32:31 +09:00
bmap.c nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
bmap.h nilfs2: get rid of GCDAT inode 2010-10-23 09:24:38 +09:00
btnode.c mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
btnode.h mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
btree.c nilfs2: apply read-ahead for nilfs_btree_lookup_contig 2010-07-23 10:02:16 +09:00
btree.h nilfs2: get rid of nilfs_bmap_union 2010-07-23 10:02:14 +09:00
cpfile.c nilfs2: see state of root dentry for mount check of snapshots 2010-10-23 09:24:38 +09:00
cpfile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dat.c nilfs2: fix typo in comment of nilfs_dat_move function 2010-11-24 12:51:48 +09:00
dat.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dir.c nilfs2: do not pass sbi to functions which can get it from inode 2011-01-10 14:37:54 +09:00
direct.c nilfs2: remove redundant pointer checks in bmap lookup functions 2010-07-23 10:02:14 +09:00
direct.h nilfs2: get rid of nilfs_bmap_union 2010-07-23 10:02:14 +09:00
export.h nilfs2: make snapshots in checkpoint tree exportable 2010-10-23 09:24:34 +09:00
file.c nilfs2: fiemap support 2011-01-10 14:05:46 +09:00
gcinode.c nilfs2: fix regression of garbage collection ioctl 2010-12-16 14:35:18 +09:00
ifile.c nilfs2: call nilfs_error inside bmap routines 2011-01-10 14:05:45 +09:00
ifile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
inode.c nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
ioctl.c nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
mdt.c mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
mdt.h nilfs2: remove own inode allocator and destructor for metadata files 2010-10-23 09:24:39 +09:00
namei.c nilfs2: fiemap support 2011-01-10 14:05:46 +09:00
nilfs.h nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
page.c mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
page.h mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
recovery.c nilfs2: do not pass sbi to functions which can get it from inode 2011-01-10 14:37:54 +09:00
sb.h nilfs2: get rid of nilfs_mount_options structure 2011-01-10 14:05:46 +09:00
segbuf.c nilfs2: get rid of bdi from nilfs object 2010-10-23 09:24:39 +09:00
segbuf.h nilfs2: get rid of macros for segment summary information 2010-07-23 10:02:09 +09:00
segment.c nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
segment.h nilfs2: use root object to get ifile 2010-10-23 09:24:35 +09:00
sufile.c nilfs2: get rid of mi_nilfs back pointer to nilfs object 2010-10-23 09:24:38 +09:00
sufile.h nilfs2: get rid of mi_nilfs back pointer to nilfs object 2010-10-23 09:24:38 +09:00
super.c mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
the_nilfs.c nilfs2: unfold nilfs_dat_inode function 2011-01-10 14:38:39 +09:00
the_nilfs.h nilfs2: get rid of loaded flag from nilfs object 2011-01-10 14:05:46 +09:00