Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+71 −50
Original line number Original line Diff line number Diff line
@@ -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
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(


	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 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)
	if (error)
			xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
		goto out;
				__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;
}
}