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

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
...@@ -417,6 +417,38 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = { ...@@ -417,6 +417,38 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
.cancel_item = xfs_refcount_update_cancel_item, .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. * Process a refcount update intent item that was recovered from the log.
* We need to update the refcountbt. * We need to update the refcountbt.
...@@ -433,11 +465,9 @@ xfs_cui_item_recover( ...@@ -433,11 +465,9 @@ xfs_cui_item_recover(
struct xfs_trans *tp; struct xfs_trans *tp;
struct xfs_btree_cur *rcur = NULL; struct xfs_btree_cur *rcur = NULL;
struct xfs_mount *mp = lip->li_mountp; struct xfs_mount *mp = lip->li_mountp;
xfs_fsblock_t startblock_fsb;
xfs_fsblock_t new_fsb; xfs_fsblock_t new_fsb;
xfs_extlen_t new_len; xfs_extlen_t new_len;
unsigned int refc_type; unsigned int refc_type;
bool op_ok;
bool requeue_only = false; bool requeue_only = false;
enum xfs_refcount_intent_type type; enum xfs_refcount_intent_type type;
int i; int i;
...@@ -449,26 +479,13 @@ xfs_cui_item_recover( ...@@ -449,26 +479,13 @@ xfs_cui_item_recover(
* just toss the CUI. * just toss the CUI.
*/ */
for (i = 0; i < cuip->cui_format.cui_nextents; i++) { for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
refc = &cuip->cui_format.cui_extents[i]; if (!xfs_cui_validate_phys(mp,
startblock_fsb = XFS_BB_TO_FSB(mp, &cuip->cui_format.cui_extents[i])) {
XFS_FSB_TO_DADDR(mp, refc->pe_startblock)); XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) { &cuip->cui_format,
case XFS_REFCOUNT_INCREASE: sizeof(cuip->cui_format));
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 -EFSCORRUPTED; return -EFSCORRUPTED;
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment