summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Blyakher <felixb@sgi.com>2009-05-07 19:49:45 -0500
committerFelix Blyakher <felixb@sgi.com>2009-06-01 22:59:29 -0500
commit1f23920dbf1377fa9e4aef4f3d20c34a06a71a35 (patch)
tree0fa80478499f1c42b2dc649659e1d1f22c6862f2
parent28e211700a81b0a934b6c7a4b8e7dda843634d2f (diff)
downloadlinux-3.10-1f23920dbf1377fa9e4aef4f3d20c34a06a71a35.tar.gz
linux-3.10-1f23920dbf1377fa9e4aef4f3d20c34a06a71a35.tar.bz2
linux-3.10-1f23920dbf1377fa9e4aef4f3d20c34a06a71a35.zip
xfs: fix double unlock in xfs_swap_extents()
Regreesion from commit ef8f7fc, which rearranged the code in xfs_swap_extents() leading to double unlock of xfs inode ilock. That resulted in xfs_fsr deadlocking itself on platforms, which don't handle double unlock of rw_semaphore nicely. It caused the count go negative, which represents the write holder, without really having one. ia64 is one of the platforms where deadlock was easily reproduced and the fix was tested. Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Reviewed-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Felix Blyakher <felixb@sgi.com>
-rw-r--r--fs/xfs/xfs_dfrag.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index e6d839bddbf..7465f9ee125 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -347,13 +347,15 @@ xfs_swap_extents(
error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT);
-out_unlock:
- xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
- xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
out:
kmem_free(tempifp);
return error;
+out_unlock:
+ xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ goto out;
+
out_trans_cancel:
xfs_trans_cancel(tp, 0);
goto out_unlock;