xfs: fix unlock in xfs_bmap_add_attrfork
xfs_trans_ijoin() activates the inode in a transaction and also can specify which lock to free when the transaction is committed or canceled. xfs_bmap_add_attrfork call locks and adds the lock to the transaction but also manually removes the lock. Change the routine to not add the lock to the transaction and manually remove lock on completion. While here, clean up the xfs_trans_cancel flags and goto names. Signed-off-by: Mark Tinguely <tinguely@sgi.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
@ -1137,6 +1137,7 @@ xfs_bmap_add_attrfork(
|
|||||||
int committed; /* xaction was committed */
|
int committed; /* xaction was committed */
|
||||||
int logflags; /* logging flags */
|
int logflags; /* logging flags */
|
||||||
int error; /* error return value */
|
int error; /* error return value */
|
||||||
|
int cancel_flags = 0;
|
||||||
|
|
||||||
ASSERT(XFS_IFORK_Q(ip) == 0);
|
ASSERT(XFS_IFORK_Q(ip) == 0);
|
||||||
|
|
||||||
@ -1147,19 +1148,20 @@ xfs_bmap_add_attrfork(
|
|||||||
if (rsvd)
|
if (rsvd)
|
||||||
tp->t_flags |= XFS_TRANS_RESERVE;
|
tp->t_flags |= XFS_TRANS_RESERVE;
|
||||||
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_addafork, blks, 0);
|
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_addafork, blks, 0);
|
||||||
if (error)
|
if (error) {
|
||||||
goto error0;
|
xfs_trans_cancel(tp, 0);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
|
error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
|
||||||
XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
|
XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
|
||||||
XFS_QMOPT_RES_REGBLKS);
|
XFS_QMOPT_RES_REGBLKS);
|
||||||
if (error) {
|
if (error)
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
goto trans_cancel;
|
||||||
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
|
cancel_flags |= XFS_TRANS_ABORT;
|
||||||
return error;
|
|
||||||
}
|
|
||||||
if (XFS_IFORK_Q(ip))
|
if (XFS_IFORK_Q(ip))
|
||||||
goto error1;
|
goto trans_cancel;
|
||||||
if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
|
if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
|
||||||
/*
|
/*
|
||||||
* For inodes coming from pre-6.2 filesystems.
|
* For inodes coming from pre-6.2 filesystems.
|
||||||
@ -1169,7 +1171,7 @@ xfs_bmap_add_attrfork(
|
|||||||
}
|
}
|
||||||
ASSERT(ip->i_d.di_anextents == 0);
|
ASSERT(ip->i_d.di_anextents == 0);
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
|
|
||||||
switch (ip->i_d.di_format) {
|
switch (ip->i_d.di_format) {
|
||||||
@ -1191,7 +1193,7 @@ xfs_bmap_add_attrfork(
|
|||||||
default:
|
default:
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
error = XFS_ERROR(EINVAL);
|
error = XFS_ERROR(EINVAL);
|
||||||
goto error1;
|
goto trans_cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(ip->i_afp == NULL);
|
ASSERT(ip->i_afp == NULL);
|
||||||
@ -1219,7 +1221,7 @@ xfs_bmap_add_attrfork(
|
|||||||
if (logflags)
|
if (logflags)
|
||||||
xfs_trans_log_inode(tp, ip, logflags);
|
xfs_trans_log_inode(tp, ip, logflags);
|
||||||
if (error)
|
if (error)
|
||||||
goto error2;
|
goto bmap_cancel;
|
||||||
if (!xfs_sb_version_hasattr(&mp->m_sb) ||
|
if (!xfs_sb_version_hasattr(&mp->m_sb) ||
|
||||||
(!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
|
(!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
|
||||||
__int64_t sbfields = 0;
|
__int64_t sbfields = 0;
|
||||||
@ -1242,14 +1244,16 @@ xfs_bmap_add_attrfork(
|
|||||||
|
|
||||||
error = xfs_bmap_finish(&tp, &flist, &committed);
|
error = xfs_bmap_finish(&tp, &flist, &committed);
|
||||||
if (error)
|
if (error)
|
||||||
goto error2;
|
goto bmap_cancel;
|
||||||
return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
||||||
error2:
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_bmap_cancel(&flist);
|
return error;
|
||||||
error1:
|
|
||||||
|
bmap_cancel:
|
||||||
|
xfs_bmap_cancel(&flist);
|
||||||
|
trans_cancel:
|
||||||
|
xfs_trans_cancel(tp, cancel_flags);
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
error0:
|
|
||||||
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user