linux/fs/gfs2
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
..
acl.c fs: provide rcu-walk aware permission i_ops 2011-01-07 17:50:29 +11:00
acl.h fs: provide rcu-walk aware permission i_ops 2011-01-07 17:50:29 +11:00
aops.c fs: kill block_prepare_write 2010-10-25 21:18:20 -04:00
bmap.c GFS2: Fix uninitialised error value in previous patch 2010-11-30 15:46:02 +00:00
bmap.h GFS2: New truncate sequence 2010-09-20 11:18:16 +01:00
dentry.c fs: rcu-walk aware d_revalidate method 2011-01-07 17:50:29 +11:00
dir.c GFS2: Make . and .. qstrs constant 2010-09-20 11:21:09 +01:00
dir.h GFS2: Make . and .. qstrs constant 2010-09-20 11:21:09 +01:00
export.c switch gfs2, close races 2011-01-12 20:02:46 -05:00
file.c fallocate should be a file operation 2011-01-17 02:25:31 -05:00
gfs2.h [GFS2] Remove remote lock dropping code 2008-06-27 09:39:44 +01:00
glock.c workqueue, freezer: unify spelling of 'freeze' + 'able' to 'freezable' 2011-02-16 17:48:59 +01:00
glock.h GFS2: Remove duplicate #defines from glock.h 2010-11-30 15:33:04 +00:00
glops.c GFS2: Don't flush delete workqueue when releasing the transaction lock 2010-12-16 15:18:48 +00:00
glops.h GFS2: Add a "demote a glock" interface to sysfs 2009-03-24 11:21:22 +00:00
incore.h headers: kobject.h redux 2011-01-10 08:51:44 -08:00
inode.c GFS2: Fix error path in gfs2_lookup_by_inum() 2011-01-18 14:49:08 +00:00
inode.h GFS2: Fix error path in gfs2_lookup_by_inum() 2011-01-18 14:49:08 +00:00
Kconfig GFS2: No longer experimental 2010-09-20 11:18:46 +01:00
lock_dlm.c GFS2: Merge glock state fields into a bitfield 2010-11-30 15:49:31 +00:00
log.c Merge branch 'v2.6.36-rc8' into for-2.6.37/barrier 2010-10-19 09:13:04 +02:00
log.h GFS2: Rework reclaiming unlinked dinodes 2010-05-21 16:11:36 +01:00
lops.c GFS2: Various gfs2_logd improvements 2010-05-05 09:39:18 +01:00
lops.h
main.c mm: prevent concurrent unmap_mapping_range() on the same inode 2011-02-23 19:52:52 -08:00
Makefile GFS2: Rename eattr.[ch] as xattr.[ch] 2009-08-26 18:51:04 +01:00
meta_io.c writeback: remove nonblocking/encountered_congestion references 2010-10-26 16:52:05 -07:00
meta_io.h GFS2: Metadata address space clean up 2010-03-01 14:07:37 +00:00
ops_fstype.c Merge branch 'for-2.6.38/core' of git://git.kernel.dk/linux-2.6-block 2011-01-13 10:45:01 -08:00
ops_inode.c fallocate should be a file operation 2011-01-17 02:25:31 -05:00
quota.c GFS2: Allow gfs2 to update quota usage values through the quotactl interface 2010-11-30 10:31:27 +00:00
quota.h mm: add context argument to shrinker callback 2010-07-19 14:56:17 +10:00
recovery.c GFS2: Fix spectator umount issue 2010-09-29 14:20:52 +01:00
recovery.h gfs2: use workqueue instead of slow-work 2010-07-23 13:14:25 +02:00
rgrp.c GFS2: fsck.gfs2 reported statfs error after gfs2_grow 2010-12-07 18:55:07 +00:00
rgrp.h GFS2: fix recursive locking during rindex truncates 2010-11-30 15:41:54 +00:00
super.c GFS2: remove iopen glocks from cache on failed deletes 2011-01-18 14:28:29 +00:00
super.h gfs: constify xattr_handler 2010-05-21 18:31:20 -04:00
sys.c GFS2: Fix type mapping for demote_rq interface 2010-10-06 09:58:44 +01:00
sys.h GFS2: Remove ancient, unused code 2009-01-05 07:39:13 +00:00
trace_gfs2.h GFS2: Don't enforce min hold time when two demotes occur in rapid succession 2010-09-20 11:19:50 +01:00
trans.c GFS2: Various gfs2_logd improvements 2010-05-05 09:39:18 +01:00
trans.h GFS2: reserve more blocks for transactions 2010-09-28 09:44:24 +01:00
util.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
util.h GFS2: Metadata address space clean up 2010-03-01 14:07:37 +00:00
xattr.c GFS2: Clean up duplicated setattr code 2010-11-30 10:30:19 +00:00
xattr.h sanitize xattr handler prototypes 2009-12-16 12:16:49 -05:00