aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-02-13 13:26:42 +0000
committerAlex Elder <aelder@sgi.com>2011-02-22 20:32:28 -0600
commitec3ba85f4083d10e32fe58b46db02d78ef71f6b8 (patch)
treebf8e3b41e913c80f24673b87fb390ce6903d82ac /fs/xfs/xfs_vnodeops.c
parent1050c71e2925ab0cb025e4c89e08b15529a1ee36 (diff)
downloadkernel_samsung_smdk4412-ec3ba85f4083d10e32fe58b46db02d78ef71f6b8.zip
kernel_samsung_smdk4412-ec3ba85f4083d10e32fe58b46db02d78ef71f6b8.tar.gz
kernel_samsung_smdk4412-ec3ba85f4083d10e32fe58b46db02d78ef71f6b8.tar.bz2
xfs: more sensible inode refcounting for ialloc
Currently we return iodes from xfs_ialloc with just a single reference held. But we need two references, as one is dropped during transaction commit and the second needs to be transfered to the VFS. Change xfs_ialloc to use xfs_iget plus xfs_trans_ijoin_ref to grab two references to the inode, and remove the now superflous IHOLD calls from all callers. This also greatly simplifies the error handling in xfs_create and also allow to remove xfs_trans_iget as no other callers are left. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c61
1 files changed, 16 insertions, 45 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index d8e6f8c..258d4f9 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1310,7 +1310,7 @@ xfs_create(
error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error)
- goto std_return;
+ return error;
if (is_dir) {
rdev = 0;
@@ -1390,12 +1390,6 @@ xfs_create(
}
/*
- * At this point, we've gotten a newly allocated inode.
- * It is locked (and joined to the transaction).
- */
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
- /*
* Now we join the directory inode to the transaction. We do not do it
* earlier because xfs_dir_ialloc might commit the previous transaction
* (and release all the locks). An error from here on will result in
@@ -1440,22 +1434,13 @@ xfs_create(
*/
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
- /*
- * xfs_trans_commit normally decrements the vnode ref count
- * when it unlocks the inode. Since we want to return the
- * vnode to the caller, we bump the vnode ref count now.
- */
- IHOLD(ip);
-
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
- goto out_abort_rele;
+ goto out_bmap_cancel;
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
- if (error) {
- IRELE(ip);
- goto out_dqrele;
- }
+ if (error)
+ goto out_release_inode;
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
@@ -1469,27 +1454,21 @@ xfs_create(
cancel_flags |= XFS_TRANS_ABORT;
out_trans_cancel:
xfs_trans_cancel(tp, cancel_flags);
- out_dqrele:
+ out_release_inode:
+ /*
+ * Wait until after the current transaction is aborted to
+ * release the inode. This prevents recursive transactions
+ * and deadlocks from xfs_inactive.
+ */
+ if (ip)
+ IRELE(ip);
+
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- std_return:
return error;
-
- out_abort_rele:
- /*
- * Wait until after the current transaction is aborted to
- * release the inode. This prevents recursive transactions
- * and deadlocks from xfs_inactive.
- */
- xfs_bmap_cancel(&free_list);
- cancel_flags |= XFS_TRANS_ABORT;
- xfs_trans_cancel(tp, cancel_flags);
- IRELE(ip);
- unlock_dp_on_error = B_FALSE;
- goto out_dqrele;
}
#ifdef DEBUG
@@ -2114,9 +2093,8 @@ xfs_symlink(
XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
&first_block, resblks, mval, &nmaps,
&free_list);
- if (error) {
- goto error1;
- }
+ if (error)
+ goto error2;
if (resblks)
resblks -= fs_blocks;
@@ -2148,7 +2126,7 @@ xfs_symlink(
error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
&first_block, &free_list, resblks);
if (error)
- goto error1;
+ goto error2;
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
@@ -2161,13 +2139,6 @@ xfs_symlink(
xfs_trans_set_sync(tp);
}
- /*
- * xfs_trans_commit normally decrements the vnode ref count
- * when it unlocks the inode. Since we want to return the
- * vnode to the caller, we bump the vnode ref count now.
- */
- IHOLD(ip);
-
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error) {
goto error2;