Commit 4d89e20b authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner

xfs: separate freelist fixing into a separate helper

Break up xfs_free_extent() into a helper that fixes the freelist.
This helper will be used subsequently to ensure the freelist during
deferred rmap processing.

[darrick: refactor to put this at the head of the patchset]
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 59bad075
...@@ -2658,55 +2658,79 @@ xfs_alloc_vextent( ...@@ -2658,55 +2658,79 @@ xfs_alloc_vextent(
return error; return error;
} }
/* /* Ensure that the freelist is at full capacity. */
* Free an extent. int
* Just break up the extent address and hand off to xfs_free_ag_extent xfs_free_extent_fix_freelist(
* after fixing up the freelist. struct xfs_trans *tp,
*/ xfs_agnumber_t agno,
int /* error */ struct xfs_buf **agbp)
xfs_free_extent(
xfs_trans_t *tp, /* transaction pointer */
xfs_fsblock_t bno, /* starting block number of extent */
xfs_extlen_t len) /* length of extent */
{ {
xfs_alloc_arg_t args; struct xfs_alloc_arg args;
int error; int error;
ASSERT(len != 0); memset(&args, 0, sizeof(struct xfs_alloc_arg));
memset(&args, 0, sizeof(xfs_alloc_arg_t));
args.tp = tp; args.tp = tp;
args.mp = tp->t_mountp; args.mp = tp->t_mountp;
args.agno = agno;
/* /*
* validate that the block number is legal - the enables us to detect * validate that the block number is legal - the enables us to detect
* and handle a silent filesystem corruption rather than crashing. * and handle a silent filesystem corruption rather than crashing.
*/ */
args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
if (args.agno >= args.mp->m_sb.sb_agcount) if (args.agno >= args.mp->m_sb.sb_agcount)
return -EFSCORRUPTED; return -EFSCORRUPTED;
args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
if (args.agbno >= args.mp->m_sb.sb_agblocks)
return -EFSCORRUPTED;
args.pag = xfs_perag_get(args.mp, args.agno); args.pag = xfs_perag_get(args.mp, args.agno);
ASSERT(args.pag); ASSERT(args.pag);
error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
if (error) if (error)
goto error0; goto out;
*agbp = args.agbp;
out:
xfs_perag_put(args.pag);
return error;
}
/*
* Free an extent.
* Just break up the extent address and hand off to xfs_free_ag_extent
* after fixing up the freelist.
*/
int /* error */
xfs_free_extent(
struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t bno, /* starting block number of extent */
xfs_extlen_t len) /* length of extent */
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *agbp;
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
int error;
ASSERT(len != 0);
error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
if (error)
return error;
XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err);
/* validate the extent size is legal now we have the agf locked */ /* validate the extent size is legal now we have the agf locked */
if (args.agbno + len > XFS_WANT_CORRUPTED_GOTO(mp,
be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
error = -EFSCORRUPTED; err);
goto error0;
}
error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0);
if (!error) if (error)
xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0); goto err;
error0:
xfs_perag_put(args.pag); xfs_extent_busy_insert(tp, agno, agbno, len, 0);
return 0;
err:
xfs_trans_brelse(tp, agbp);
return error; return error;
} }
...@@ -236,5 +236,7 @@ xfs_alloc_get_rec( ...@@ -236,5 +236,7 @@ xfs_alloc_get_rec(
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
struct xfs_buf **agbp);
#endif /* __XFS_ALLOC_H__ */ #endif /* __XFS_ALLOC_H__ */
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