Commit 88877d2b authored by Brian Foster's avatar Brian Foster Committed by Ben Myers

xfs: push down inactive transaction mgmt for ifree

Push the inode free work performed during xfs_inactive() down into
a new xfs_inactive_ifree() helper. This clears xfs_inactive() from
all inode locking and transaction management more directly
associated with freeing the inode xattrs, extents and the inode
itself.
Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent f7be2d7f
...@@ -1714,6 +1714,74 @@ xfs_inactive_truncate( ...@@ -1714,6 +1714,74 @@ xfs_inactive_truncate(
return error; return error;
} }
/*
* xfs_inactive_ifree()
*
* Perform the inode free when an inode is unlinked.
*/
STATIC int
xfs_inactive_ifree(
struct xfs_inode *ip)
{
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
int committed;
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
int error;
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
if (error) {
ASSERT(XFS_FORCED_SHUTDOWN(mp));
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
xfs_bmap_init(&free_list, &first_block);
error = xfs_ifree(tp, ip, &free_list);
if (error) {
/*
* If we fail to free the inode, shut down. The cancel
* might do that, we need to make sure. Otherwise the
* inode might be lost for a long time or forever.
*/
if (!XFS_FORCED_SHUTDOWN(mp)) {
xfs_notice(mp, "%s: xfs_ifree returned error %d",
__func__, error);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
}
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return error;
}
/*
* Credit the quota account(s). The inode is gone.
*/
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
/*
* Just ignore errors at this point. There is nothing we can
* do except to try to keep going. Make sure it's not a silent
* error.
*/
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
__func__, error);
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
if (error)
xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
__func__, error);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return 0;
}
/* /*
* xfs_inactive * xfs_inactive
* *
...@@ -1726,10 +1794,6 @@ int ...@@ -1726,10 +1794,6 @@ int
xfs_inactive( xfs_inactive(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
xfs_bmap_free_t free_list;
xfs_fsblock_t first_block;
int committed;
struct xfs_trans *tp;
struct xfs_mount *mp; struct xfs_mount *mp;
int error; int error;
int truncate = 0; int truncate = 0;
...@@ -1801,60 +1865,17 @@ xfs_inactive( ...@@ -1801,60 +1865,17 @@ xfs_inactive(
ASSERT(ip->i_d.di_anextents == 0); ASSERT(ip->i_d.di_anextents == 0);
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
if (error) {
ASSERT(XFS_FORCED_SHUTDOWN(mp));
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
goto out;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
/* /*
* Free the inode. * Free the inode.
*/ */
xfs_bmap_init(&free_list, &first_block); error = xfs_inactive_ifree(ip);
error = xfs_ifree(tp, ip, &free_list); if (error)
if (error) { goto out;
/*
* If we fail to free the inode, shut down. The cancel
* might do that, we need to make sure. Otherwise the
* inode might be lost for a long time or forever.
*/
if (!XFS_FORCED_SHUTDOWN(mp)) {
xfs_notice(mp, "%s: xfs_ifree returned error %d",
__func__, error);
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
}
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
} else {
/*
* Credit the quota account(s). The inode is gone.
*/
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
/*
* Just ignore errors at this point. There is nothing we can
* do except to try to keep going. Make sure it's not a silent
* error.
*/
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
__func__, error);
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
if (error)
xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
__func__, error);
}
/* /*
* Release the dquots held by inode, if any. * Release the dquots held by inode, if any.
*/ */
xfs_qm_dqdetach(ip); xfs_qm_dqdetach(ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
out: out:
return VN_INACTIVE_CACHE; return VN_INACTIVE_CACHE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment