Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+54 −30
Original line number Diff line number Diff line
@@ -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;
	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;
	*agbp = args.agbp;
out:
	xfs_perag_put(args.pag);
	return error;
}

	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:
	xfs_perag_put(args.pag);
/*
 * 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;
}
+2 −0
Original line number Diff line number Diff line
@@ -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__ */