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: Dave Chinner <dchinner@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
59bad075bd
commit
4d89e20bf1
|
@ -2658,55 +2658,79 @@ xfs_alloc_vextent(
|
|||
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(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
xfs_extlen_t len) /* length of extent */
|
||||
/* Ensure that the freelist is at full capacity. */
|
||||
int
|
||||
xfs_free_extent_fix_freelist(
|
||||
struct xfs_trans *tp,
|
||||
xfs_agnumber_t agno,
|
||||
struct xfs_buf **agbp)
|
||||
{
|
||||
xfs_alloc_arg_t args;
|
||||
int error;
|
||||
struct xfs_alloc_arg args;
|
||||
int error;
|
||||
|
||||
ASSERT(len != 0);
|
||||
memset(&args, 0, sizeof(xfs_alloc_arg_t));
|
||||
memset(&args, 0, sizeof(struct xfs_alloc_arg));
|
||||
args.tp = tp;
|
||||
args.mp = tp->t_mountp;
|
||||
args.agno = agno;
|
||||
|
||||
/*
|
||||
* validate that the block number is legal - the enables us to detect
|
||||
* 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)
|
||||
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);
|
||||
ASSERT(args.pag);
|
||||
|
||||
error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
|
||||
if (error)
|
||||
goto error0;
|
||||
goto out;
|
||||
|
||||
/* validate the extent size is legal now we have the agf locked */
|
||||
if (args.agbno + len >
|
||||
be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) {
|
||||
error = -EFSCORRUPTED;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
|
||||
if (!error)
|
||||
xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0);
|
||||
error0:
|
||||
*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 */
|
||||
XFS_WANT_CORRUPTED_GOTO(mp,
|
||||
agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
|
||||
err);
|
||||
|
||||
error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0);
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
xfs_extent_busy_insert(tp, agno, agbno, len, 0);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -236,5 +236,7 @@ xfs_alloc_get_rec(
|
|||
int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
|
||||
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__ */
|
||||
|
|
Loading…
Reference in New Issue