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

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

xfs: push down inactive transaction mgmt for truncate



Create the new xfs_inactive_truncate() function to handle the
truncate portion of xfs_inactive(). Push the locking and
transaction management into the new function.

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 36b21dde
Loading
Loading
Loading
Loading
+68 −49
Original line number Original line Diff line number Diff line
@@ -1662,6 +1662,58 @@ xfs_release(
	return 0;
	return 0;
}
}


/*
 * xfs_inactive_truncate
 *
 * Called to perform a truncate when an inode becomes unlinked.
 */
STATIC int
xfs_inactive_truncate(
	struct xfs_inode *ip)
{
	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_itruncate, 0, 0);
	if (error) {
		ASSERT(XFS_FORCED_SHUTDOWN(mp));
		xfs_trans_cancel(tp, 0);
		return error;
	}

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);

	/*
	 * Log the inode size first to prevent stale data exposure in the event
	 * of a system crash before the truncate completes. See the related
	 * comment in xfs_setattr_size() for details.
	 */
	ip->i_d.di_size = 0;
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
	if (error)
		goto error_trans_cancel;

	ASSERT(ip->i_d.di_nextents == 0);

	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
	if (error)
		goto error_unlock;

	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	return 0;

error_trans_cancel:
	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
error_unlock:
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	return error;
}

/*
/*
 * xfs_inactive
 * xfs_inactive
 *
 *
@@ -1679,7 +1731,6 @@ xfs_inactive(
	int			committed;
	int			committed;
	struct xfs_trans	*tp;
	struct xfs_trans	*tp;
	struct xfs_mount	*mp;
	struct xfs_mount	*mp;
	struct xfs_trans_res	*resp;
	int			error;
	int			error;
	int			truncate = 0;
	int			truncate = 0;


@@ -1724,35 +1775,12 @@ xfs_inactive(
	if (error)
	if (error)
		return VN_INACTIVE_CACHE;
		return VN_INACTIVE_CACHE;


	if (S_ISLNK(ip->i_d.di_mode)) {
	if (S_ISLNK(ip->i_d.di_mode))
		error = xfs_inactive_symlink(ip);
		error = xfs_inactive_symlink(ip);
	else if (truncate)
		error = xfs_inactive_truncate(ip);
	if (error)
	if (error)
		goto out;
		goto out;
	}

	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
	resp = truncate ? &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree;

	error = xfs_trans_reserve(tp, resp, 0, 0);
	if (error) {
		ASSERT(XFS_FORCED_SHUTDOWN(mp));
		xfs_trans_cancel(tp, 0);
		return VN_INACTIVE_CACHE;
	}

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);

	if (truncate) {
		ip->i_d.di_size = 0;
		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

		error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
		if (error)
			goto out_cancel;

		ASSERT(ip->i_d.di_nextents == 0);
	}


	/*
	/*
	 * If there are attributes associated with the file then blow them away
	 * If there are attributes associated with the file then blow them away
@@ -1763,31 +1791,26 @@ xfs_inactive(
	if (ip->i_d.di_anextents > 0) {
	if (ip->i_d.di_anextents > 0) {
		ASSERT(ip->i_d.di_forkoff != 0);
		ASSERT(ip->i_d.di_forkoff != 0);


		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
		if (error)
			goto out_unlock;

		xfs_iunlock(ip, XFS_ILOCK_EXCL);

		error = xfs_attr_inactive(ip);
		error = xfs_attr_inactive(ip);
		if (error)
		if (error)
			goto out;
			goto out;
	}

	if (ip->i_afp)
		xfs_idestroy_fork(ip, XFS_ATTR_FORK);

	ASSERT(ip->i_d.di_anextents == 0);


	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0);
	if (error) {
	if (error) {
			xfs_trans_cancel(tp, 0);
		ASSERT(XFS_FORCED_SHUTDOWN(mp));
		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
		goto out;
		goto out;
	}
	}


	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);
	xfs_trans_ijoin(tp, ip, 0);
	}

	if (ip->i_afp)
		xfs_idestroy_fork(ip, XFS_ATTR_FORK);

	ASSERT(ip->i_d.di_anextents == 0);


	/*
	/*
	 * Free the inode.
	 * Free the inode.
@@ -1831,13 +1854,9 @@ xfs_inactive(
	 * Release the dquots held by inode, if any.
	 * Release the dquots held by inode, if any.
	 */
	 */
	xfs_qm_dqdetach(ip);
	xfs_qm_dqdetach(ip);
out_unlock:
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
out:
out:
	return VN_INACTIVE_CACHE;
	return VN_INACTIVE_CACHE;
out_cancel:
	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
	goto out_unlock;
}
}


/*
/*