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: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
Родитель
f7be2d7f59
Коммит
88877d2b97
|
@ -1714,6 +1714,74 @@ error_unlock:
|
|||
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
|
||||
*
|
||||
|
@ -1726,10 +1794,6 @@ int
|
|||
xfs_inactive(
|
||||
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;
|
||||
int error;
|
||||
int truncate = 0;
|
||||
|
@ -1801,60 +1865,17 @@ xfs_inactive(
|
|||
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
error = xfs_inactive_ifree(ip);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Release the dquots held by inode, if any.
|
||||
*/
|
||||
xfs_qm_dqdetach(ip);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
out:
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче