Commit ed64f834 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: hoist recovered refcount intent checks out of xfs_cui_item_recover



When we recover a refcount intent from the log, we need to validate its
contents before we try to replay them.  Hoist the checking code into a
separate function in preparation to refactor this code to use validation
helpers.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent c447ad62
Loading
Loading
Loading
Loading
+38 −21
Original line number Diff line number Diff line
@@ -417,6 +417,38 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
	.cancel_item	= xfs_refcount_update_cancel_item,
};

/* Is this recovered CUI ok? */
static inline bool
xfs_cui_validate_phys(
	struct xfs_mount		*mp,
	struct xfs_phys_extent		*refc)
{
	xfs_fsblock_t			startblock_fsb;
	bool				op_ok;

	startblock_fsb = XFS_BB_TO_FSB(mp,
			   XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
	switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
	case XFS_REFCOUNT_INCREASE:
	case XFS_REFCOUNT_DECREASE:
	case XFS_REFCOUNT_ALLOC_COW:
	case XFS_REFCOUNT_FREE_COW:
		op_ok = true;
		break;
	default:
		op_ok = false;
		break;
	}
	if (!op_ok || startblock_fsb == 0 ||
	    refc->pe_len == 0 ||
	    startblock_fsb >= mp->m_sb.sb_dblocks ||
	    refc->pe_len >= mp->m_sb.sb_agblocks ||
	    (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS))
		return false;

	return true;
}

/*
 * Process a refcount update intent item that was recovered from the log.
 * We need to update the refcountbt.
@@ -433,11 +465,9 @@ xfs_cui_item_recover(
	struct xfs_trans		*tp;
	struct xfs_btree_cur		*rcur = NULL;
	struct xfs_mount		*mp = lip->li_mountp;
	xfs_fsblock_t			startblock_fsb;
	xfs_fsblock_t			new_fsb;
	xfs_extlen_t			new_len;
	unsigned int			refc_type;
	bool				op_ok;
	bool				requeue_only = false;
	enum xfs_refcount_intent_type	type;
	int				i;
@@ -449,27 +479,14 @@ xfs_cui_item_recover(
	 * just toss the CUI.
	 */
	for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
		refc = &cuip->cui_format.cui_extents[i];
		startblock_fsb = XFS_BB_TO_FSB(mp,
				   XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
		switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
		case XFS_REFCOUNT_INCREASE:
		case XFS_REFCOUNT_DECREASE:
		case XFS_REFCOUNT_ALLOC_COW:
		case XFS_REFCOUNT_FREE_COW:
			op_ok = true;
			break;
		default:
			op_ok = false;
			break;
		}
		if (!op_ok || startblock_fsb == 0 ||
		    refc->pe_len == 0 ||
		    startblock_fsb >= mp->m_sb.sb_dblocks ||
		    refc->pe_len >= mp->m_sb.sb_agblocks ||
		    (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS))
		if (!xfs_cui_validate_phys(mp,
					&cuip->cui_format.cui_extents[i])) {
			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
					&cuip->cui_format,
					sizeof(cuip->cui_format));
			return -EFSCORRUPTED;
		}
	}

	/*
	 * Under normal operation, refcount updates are deferred, so we