aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2011-03-22 19:30:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-22 20:43:58 -0400
commit52c50567d8ab0a0a87f12cceaa4194967854f0bd (patch)
tree11644ba2fd533fdd39631254fc9cfc2699dfb8ae /mm
parentc7a1fcd8e6e0c3c8f4f8f74fc926ff04da3bf7a7 (diff)
mm: swap: unlock swapfile inode mutex before closing file on bad swapfiles
If an administrator tries to swapon a file backed by NFS, the inode mutex is taken (as it is for any swapfile) but later identified to be a bad swapfile due to the lack of bmap and tries to cleanup. During cleanup, an attempt is made to close the file but with inode->i_mutex still held. Closing an NFS file syncs it which tries to acquire the inode mutex leading to deadlock. If lockdep is enabled the following appears on the console; ============================================= [ INFO: possible recursive locking detected ] 2.6.38-rc8-autobuild #1 --------------------------------------------- swapon/2192 is trying to acquire lock: (&sb->s_type->i_mutex_key#13){+.+.+.}, at: vfs_fsync_range+0x47/0x7c but task is already holding lock: (&sb->s_type->i_mutex_key#13){+.+.+.}, at: sys_swapon+0x28d/0xae7 other info that might help us debug this: 1 lock held by swapon/2192: #0: (&sb->s_type->i_mutex_key#13){+.+.+.}, at: sys_swapon+0x28d/0xae7 stack backtrace: Pid: 2192, comm: swapon Not tainted 2.6.38-rc8-autobuild #1 Call Trace: __lock_acquire+0x2eb/0x1623 find_get_pages_tag+0x14a/0x174 pagevec_lookup_tag+0x25/0x2e vfs_fsync_range+0x47/0x7c lock_acquire+0xd3/0x100 vfs_fsync_range+0x47/0x7c nfs_flush_one+0x0/0xdf [nfs] mutex_lock_nested+0x40/0x2b1 vfs_fsync_range+0x47/0x7c vfs_fsync_range+0x47/0x7c vfs_fsync+0x1c/0x1e nfs_file_flush+0x64/0x69 [nfs] filp_close+0x43/0x72 sys_swapon+0xa39/0xae7 sysret_check+0x2e/0x69 system_call_fastpath+0x16/0x1b This patch releases the mutex if its held before calling filep_close() so swapon fails as expected without deadlock when the swapfile is backed by NFS. If accepted for 2.6.39, it should also be considered a -stable candidate for 2.6.38 and 2.6.37. Signed-off-by: Mel Gorman <mgorman@suse.de> Acked-by: Hugh Dickins <hughd@google.com> Cc: <stable@kernel.org> [2.6.37+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/swapfile.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 0341c5700e34..6d6d28c0a72f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2149,8 +2149,13 @@ bad_swap_2:
2149 p->flags = 0; 2149 p->flags = 0;
2150 spin_unlock(&swap_lock); 2150 spin_unlock(&swap_lock);
2151 vfree(swap_map); 2151 vfree(swap_map);
2152 if (swap_file) 2152 if (swap_file) {
2153 if (did_down) {
2154 mutex_unlock(&inode->i_mutex);
2155 did_down = 0;
2156 }
2153 filp_close(swap_file, NULL); 2157 filp_close(swap_file, NULL);
2158 }
2154out: 2159out:
2155 if (page && !IS_ERR(page)) { 2160 if (page && !IS_ERR(page)) {
2156 kunmap(page); 2161 kunmap(page);