kernel-ark/fs/nilfs2
Ryusuke Konishi 572d8b3945 nilfs2: fix deadlock issue between chcp and thaw ioctls
An fs-thaw ioctl causes deadlock with a chcp or mkcp -s command:

 chcp            D ffff88013870f3d0     0  1325   1324 0x00000004
 ...
 Call Trace:
   nilfs_transaction_begin+0x11c/0x1a0 [nilfs2]
   wake_up_bit+0x20/0x20
   copy_from_user+0x18/0x30 [nilfs2]
   nilfs_ioctl_change_cpmode+0x7d/0xcf [nilfs2]
   nilfs_ioctl+0x252/0x61a [nilfs2]
   do_page_fault+0x311/0x34c
   get_unmapped_area+0x132/0x14e
   do_vfs_ioctl+0x44b/0x490
   __set_task_blocked+0x5a/0x61
   vm_mmap_pgoff+0x76/0x87
   __set_current_blocked+0x30/0x4a
   sys_ioctl+0x4b/0x6f
   system_call_fastpath+0x16/0x1b
 thaw            D ffff88013870d890     0  1352   1351 0x00000004
 ...
 Call Trace:
   rwsem_down_failed_common+0xdb/0x10f
   call_rwsem_down_write_failed+0x13/0x20
   down_write+0x25/0x27
   thaw_super+0x13/0x9e
   do_vfs_ioctl+0x1f5/0x490
   vm_mmap_pgoff+0x76/0x87
   sys_ioctl+0x4b/0x6f
   filp_close+0x64/0x6c
   system_call_fastpath+0x16/0x1b

where the thaw ioctl deadlocked at thaw_super() when called while chcp was
waiting at nilfs_transaction_begin() called from
nilfs_ioctl_change_cpmode().  This deadlock is 100% reproducible.

This is because nilfs_ioctl_change_cpmode() first locks sb->s_umount in
read mode and then waits for unfreezing in nilfs_transaction_begin(),
whereas thaw_super() locks sb->s_umount in write mode.  The locking of
sb->s_umount here was intended to make snapshot mounts and the downgrade
of snapshots to checkpoints exclusive.

This fixes the deadlock issue by replacing the sb->s_umount usage in
nilfs_ioctl_change_cpmode() with a dedicated mutex which protects snapshot
mounts.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp>
Tested-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-30 17:25:19 -07:00
..
alloc.c nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
alloc.h nilfs2: use little-endian bitops 2011-03-23 19:46:18 -07:00
bmap.c nilfs2: get rid of NILFS_I_NILFS 2011-05-10 22:21:56 +09:00
bmap.h nilfs2: record used amount of each checkpoint in checkpoint list 2011-03-08 14:58:31 +09:00
btnode.c nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
btnode.h nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
btree.c nilfs2: fix missing block address termination in btree node shrinking 2011-06-11 15:51:15 +09:00
btree.h nilfs2: get rid of nilfs_bmap_union 2010-07-23 10:02:14 +09:00
cpfile.c nilfs2: fix timing issue between rmcp and chcp ioctls 2012-07-30 17:25:19 -07:00
cpfile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dat.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
dat.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
dir.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
direct.c nilfs2: record used amount of each checkpoint in checkpoint list 2011-03-08 14:58:31 +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: flush disk caches in syncing 2012-05-31 17:49:27 -07:00
gcinode.c nilfs2: ensure proper cache clearing for gc-inodes 2012-06-20 14:39:35 -07:00
ifile.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
ifile.h nilfs2: use iget for all metadata files 2010-10-23 09:24:38 +09:00
inode.c vfs: Rename end_writeback() to clear_inode() 2012-05-06 13:43:41 +08:00
ioctl.c nilfs2: fix deadlock issue between chcp and thaw ioctls 2012-07-30 17:25:19 -07:00
Kconfig
Makefile nilfs2: get rid of GCDAT inode 2010-10-23 09:24:38 +09:00
mdt.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
mdt.h nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
namei.c don't pass nameidata to ->create() 2012-07-14 16:34:47 +04:00
nilfs.h nilfs: propagate umode_t 2012-01-03 22:55:04 -05:00
page.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
page.h nilfs2: use mark_buffer_dirty to mark btnode or meta data dirty 2011-05-10 22:21:57 +09:00
recovery.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
segbuf.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
segbuf.h
segment.c nilfs2: ensure proper cache clearing for gc-inodes 2012-06-20 14:39:35 -07:00
segment.h nilfs2: get rid of private page allocator 2011-05-10 22:21:44 +09:00
sufile.c nilfs2: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:24 +08:00
sufile.h nilfs2: get rid of NILFS_I_NILFS 2011-05-10 22:21:56 +09:00
super.c nilfs2: fix deadlock issue between chcp and thaw ioctls 2012-07-30 17:25:19 -07:00
the_nilfs.c nilfs2: fix deadlock issue between chcp and thaw ioctls 2012-07-30 17:25:19 -07:00
the_nilfs.h nilfs2: fix deadlock issue between chcp and thaw ioctls 2012-07-30 17:25:19 -07:00