Commit 25576c54 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Chandan Babu R
Browse files

xfs: simplify iext overflow checking and upgrade



Currently the calls to xfs_iext_count_may_overflow and
xfs_iext_count_upgrade are always paired.  Merge them into a single
function to simplify the callers and the actual check and upgrade
logic itself.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>
parent 86de8484
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -1050,10 +1050,7 @@ xfs_attr_set(
		return error;

	if (op != XFS_ATTRUPDATE_REMOVE || xfs_inode_hasattr(dp)) {
		error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
		if (error == -EFBIG)
			error = xfs_iext_count_upgrade(args->trans, dp,
		error = xfs_iext_count_extend(args->trans, dp, XFS_ATTR_FORK,
				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
		if (error)
			goto out_trans_cancel;
+1 −4
Original line number Diff line number Diff line
@@ -4651,10 +4651,7 @@ xfs_bmapi_convert_one_delalloc(
	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);

	error = xfs_iext_count_may_overflow(ip, whichfork,
			XFS_IEXT_ADD_NOSPLIT_CNT);
	if (error == -EFBIG)
		error = xfs_iext_count_upgrade(tp, ip,
	error = xfs_iext_count_extend(tp, ip, whichfork,
			XFS_IEXT_ADD_NOSPLIT_CNT);
	if (error)
		goto out_trans_cancel;
+25 −32
Original line number Diff line number Diff line
@@ -765,53 +765,46 @@ xfs_ifork_verify_local_attr(
	return 0;
}

/*
 * Check if the inode fork supports adding nr_to_add more extents.
 *
 * If it doesn't but we can upgrade it to large extent counters, do the upgrade.
 * If we can't upgrade or are already using big counters but still can't fit the
 * additional extents, return -EFBIG.
 */
int
xfs_iext_count_may_overflow(
xfs_iext_count_extend(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	int			whichfork,
	int			nr_to_add)
	uint			nr_to_add)
{
	struct xfs_mount	*mp = ip->i_mount;
	bool			has_large =
		xfs_inode_has_large_extent_counts(ip);
	struct xfs_ifork	*ifp = xfs_ifork_ptr(ip, whichfork);
	uint64_t		max_exts;
	uint64_t		nr_exts;

	ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);

	if (whichfork == XFS_COW_FORK)
		return 0;

	max_exts = xfs_iext_max_nextents(xfs_inode_has_large_extent_counts(ip),
				whichfork);

	if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
		max_exts = 10;

	/* no point in upgrading if if_nextents overflows */
	nr_exts = ifp->if_nextents + nr_to_add;
	if (nr_exts < ifp->if_nextents || nr_exts > max_exts)
	if (nr_exts < ifp->if_nextents)
		return -EFBIG;

	return 0;
}

/*
 * Upgrade this inode's extent counter fields to be able to handle a potential
 * increase in the extent count by nr_to_add.  Normally this is the same
 * quantity that caused xfs_iext_count_may_overflow() to return -EFBIG.
 */
int
xfs_iext_count_upgrade(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	uint			nr_to_add)
{
	ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);

	if (!xfs_has_large_extent_counts(ip->i_mount) ||
	    xfs_inode_has_large_extent_counts(ip) ||
	    XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
	if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REDUCE_MAX_IEXTENTS) &&
	    nr_exts > 10)
		return -EFBIG;

	if (nr_exts > xfs_iext_max_nextents(has_large, whichfork)) {
		if (has_large || !xfs_has_large_extent_counts(mp))
			return -EFBIG;
		ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	}
	return 0;
}

+2 −4
Original line number Diff line number Diff line
@@ -256,10 +256,8 @@ extern void xfs_ifork_init_cow(struct xfs_inode *ip);

int xfs_ifork_verify_local_data(struct xfs_inode *ip);
int xfs_ifork_verify_local_attr(struct xfs_inode *ip);
int xfs_iext_count_may_overflow(struct xfs_inode *ip, int whichfork,
		int nr_to_add);
int xfs_iext_count_upgrade(struct xfs_trans *tp, struct xfs_inode *ip,
		uint nr_to_add);
int xfs_iext_count_extend(struct xfs_trans *tp, struct xfs_inode *ip,
		int whichfork, uint nr_to_add);
bool xfs_ifork_is_realtime(struct xfs_inode *ip, int whichfork);

/* returns true if the fork has extents but they are not read in yet. */
+1 −3
Original line number Diff line number Diff line
@@ -524,9 +524,7 @@ xfs_bmap_recover_work(
	else
		iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;

	error = xfs_iext_count_may_overflow(ip, work->bi_whichfork, iext_delta);
	if (error == -EFBIG)
		error = xfs_iext_count_upgrade(tp, ip, iext_delta);
	error = xfs_iext_count_extend(tp, ip, work->bi_whichfork, iext_delta);
	if (error)
		goto err_cancel;

Loading