Commit 06e4e940 authored by Chandan Babu R's avatar Chandan Babu R
Browse files

Merge tag 'extfree-intent-cleanups-6.11_2024-07-02' of...

Merge tag 'extfree-intent-cleanups-6.11_2024-07-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.11-mergeB

xfs: extent free log intent cleanups

This series cleans up some warts in the extent freeing log intent code.
We start by acknowledging that this mechanism does not have anything to
do with the bmap code by moving it to xfs_alloc.c and giving the
function a more descriptive name.  Then we clean up the tracepoints and
the _finish_one call paths to pass the intent structure around.  This
reduces the overhead when the tracepoints are disabled and will make
things much cleaner when we start adding realtime support in the next
patch.  I also incorporated a bunch of cleanups from Christoph Hellwig.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>

* tag 'extfree-intent-cleanups-6.11_2024-07-02' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: move xfs_extent_free_defer_add to xfs_extfree_item.c
  xfs: remove xfs_defer_agfl_block
  xfs: remove duplicate asserts in xfs_defer_extent_free
  xfs: factor out a xfs_efd_add_extent helper
  xfs: reuse xfs_extent_free_cancel_item
  xfs: add a xefi_entry helper
  xfs: pass the fsbno to xfs_perag_intent_get
  xfs: convert "skip_discard" to a proper flags bitset
  xfs: clean up extent free log intent item tracepoint callsites
parents 2f6ebd4c 84a3c157
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1008,7 +1008,7 @@ xfs_ag_shrink_space(
			goto resv_err;

		err2 = xfs_free_extent_later(*tpp, args.fsbno, delta, NULL,
				XFS_AG_RESV_NONE, true);
				XFS_AG_RESV_NONE, XFS_FREE_EXTENT_SKIP_DISCARD);
		if (err2)
			goto resv_err;

+24 −69
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "xfs_ag_resv.h"
#include "xfs_bmap.h"
#include "xfs_health.h"
#include "xfs_extfree_item.h"

struct kmem_cache	*xfs_extfree_item_cache;

@@ -2509,48 +2510,6 @@ xfs_agfl_reset(
	clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
}

/*
 * Defer an AGFL block free. This is effectively equivalent to
 * xfs_free_extent_later() with some special handling particular to AGFL blocks.
 *
 * Deferring AGFL frees helps prevent log reservation overruns due to too many
 * allocation operations in a transaction. AGFL frees are prone to this problem
 * because for one they are always freed one at a time. Further, an immediate
 * AGFL block free can cause a btree join and require another block free before
 * the real allocation can proceed. Deferring the free disconnects freeing up
 * the AGFL slot from freeing the block.
 */
static int
xfs_defer_agfl_block(
	struct xfs_trans		*tp,
	xfs_agnumber_t			agno,
	xfs_agblock_t			agbno,
	struct xfs_owner_info		*oinfo)
{
	struct xfs_mount		*mp = tp->t_mountp;
	struct xfs_extent_free_item	*xefi;
	xfs_fsblock_t			fsbno = XFS_AGB_TO_FSB(mp, agno, agbno);

	ASSERT(xfs_extfree_item_cache != NULL);
	ASSERT(oinfo != NULL);

	if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, fsbno)))
		return -EFSCORRUPTED;

	xefi = kmem_cache_zalloc(xfs_extfree_item_cache,
			       GFP_KERNEL | __GFP_NOFAIL);
	xefi->xefi_startblock = fsbno;
	xefi->xefi_blockcount = 1;
	xefi->xefi_owner = oinfo->oi_owner;
	xefi->xefi_agresv = XFS_AG_RESV_AGFL;

	trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);

	xfs_extent_free_get_group(mp, xefi);
	xfs_defer_add(tp, &xefi->xefi_list, &xfs_agfl_free_defer_type);
	return 0;
}

/*
 * Add the extent to the list of extents to be free at transaction end.
 * The list is maintained sorted (by block number).
@@ -2562,28 +2521,15 @@ xfs_defer_extent_free(
	xfs_filblks_t			len,
	const struct xfs_owner_info	*oinfo,
	enum xfs_ag_resv_type		type,
	bool				skip_discard,
	unsigned int			free_flags,
	struct xfs_defer_pending	**dfpp)
{
	struct xfs_extent_free_item	*xefi;
	struct xfs_mount		*mp = tp->t_mountp;
#ifdef DEBUG
	xfs_agnumber_t			agno;
	xfs_agblock_t			agbno;

	ASSERT(bno != NULLFSBLOCK);
	ASSERT(len > 0);
	ASSERT(len <= XFS_MAX_BMBT_EXTLEN);
	ASSERT(!isnullstartblock(bno));
	agno = XFS_FSB_TO_AGNO(mp, bno);
	agbno = XFS_FSB_TO_AGBNO(mp, bno);
	ASSERT(agno < mp->m_sb.sb_agcount);
	ASSERT(agbno < mp->m_sb.sb_agblocks);
	ASSERT(len < mp->m_sb.sb_agblocks);
	ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
#endif
	ASSERT(xfs_extfree_item_cache != NULL);
	ASSERT(type != XFS_AG_RESV_AGFL);
	ASSERT(!(free_flags & ~XFS_FREE_EXTENT_ALL_FLAGS));

	if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len)))
		return -EFSCORRUPTED;
@@ -2593,7 +2539,7 @@ xfs_defer_extent_free(
	xefi->xefi_startblock = bno;
	xefi->xefi_blockcount = (xfs_extlen_t)len;
	xefi->xefi_agresv = type;
	if (skip_discard)
	if (free_flags & XFS_FREE_EXTENT_SKIP_DISCARD)
		xefi->xefi_flags |= XFS_EFI_SKIP_DISCARD;
	if (oinfo) {
		ASSERT(oinfo->oi_offset == 0);
@@ -2606,12 +2552,8 @@ xfs_defer_extent_free(
	} else {
		xefi->xefi_owner = XFS_RMAP_OWN_NULL;
	}
	trace_xfs_bmap_free_defer(mp,
			XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
			XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);

	xfs_extent_free_get_group(mp, xefi);
	*dfpp = xfs_defer_add(tp, &xefi->xefi_list, &xfs_extent_free_defer_type);
	xfs_extent_free_defer_add(tp, xefi, dfpp);
	return 0;
}

@@ -2622,11 +2564,11 @@ xfs_free_extent_later(
	xfs_filblks_t			len,
	const struct xfs_owner_info	*oinfo,
	enum xfs_ag_resv_type		type,
	bool				skip_discard)
	unsigned int			free_flags)
{
	struct xfs_defer_pending	*dontcare = NULL;

	return xfs_defer_extent_free(tp, bno, len, oinfo, type, skip_discard,
	return xfs_defer_extent_free(tp, bno, len, oinfo, type, free_flags,
			&dontcare);
}

@@ -2651,13 +2593,13 @@ xfs_free_extent_later(
int
xfs_alloc_schedule_autoreap(
	const struct xfs_alloc_arg	*args,
	bool				skip_discard,
	unsigned int			free_flags,
	struct xfs_alloc_autoreap	*aarp)
{
	int				error;

	error = xfs_defer_extent_free(args->tp, args->fsbno, args->len,
			&args->oinfo, args->resv, skip_discard, &aarp->dfp);
			&args->oinfo, args->resv, free_flags, &aarp->dfp);
	if (error)
		return error;

@@ -2869,8 +2811,21 @@ xfs_alloc_fix_freelist(
		if (error)
			goto out_agbp_relse;

		/* defer agfl frees */
		error = xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo);
		/*
		 * Defer the AGFL block free.
		 *
		 * This helps to prevent log reservation overruns due to too
		 * many allocation operations in a transaction. AGFL frees are
		 * prone to this problem because for one they are always freed
		 * one at a time.  Further, an immediate AGFL block free can
		 * cause a btree join and require another block free before the
		 * real allocation can proceed.
		 * Deferring the free disconnects freeing up the AGFL slot from
		 * freeing the block.
		 */
		error = xfs_free_extent_later(tp,
				XFS_AGB_TO_FSB(mp, args->agno, bno), 1,
				&targs.oinfo, XFS_AG_RESV_AGFL, 0);
		if (error)
			goto out_agbp_relse;
	}
+7 −5
Original line number Diff line number Diff line
@@ -235,7 +235,12 @@ xfs_buf_to_agfl_bno(

int xfs_free_extent_later(struct xfs_trans *tp, xfs_fsblock_t bno,
		xfs_filblks_t len, const struct xfs_owner_info *oinfo,
		enum xfs_ag_resv_type type, bool skip_discard);
		enum xfs_ag_resv_type type, unsigned int free_flags);

/* Don't issue a discard for the blocks freed. */
#define XFS_FREE_EXTENT_SKIP_DISCARD	(1U << 0)

#define XFS_FREE_EXTENT_ALL_FLAGS	(XFS_FREE_EXTENT_SKIP_DISCARD)

/*
 * List of extents to be free "later".
@@ -251,9 +256,6 @@ struct xfs_extent_free_item {
	enum xfs_ag_resv_type	xefi_agresv;
};

void xfs_extent_free_get_group(struct xfs_mount *mp,
		struct xfs_extent_free_item *xefi);

#define XFS_EFI_SKIP_DISCARD	(1U << 0) /* don't issue discard */
#define XFS_EFI_ATTR_FORK	(1U << 1) /* freeing attr fork block */
#define XFS_EFI_BMBT_BLOCK	(1U << 2) /* freeing bmap btree block */
@@ -264,7 +266,7 @@ struct xfs_alloc_autoreap {
};

int xfs_alloc_schedule_autoreap(const struct xfs_alloc_arg *args,
		bool skip_discard, struct xfs_alloc_autoreap *aarp);
		unsigned int free_flags, struct xfs_alloc_autoreap *aarp);
void xfs_alloc_cancel_autoreap(struct xfs_trans *tp,
		struct xfs_alloc_autoreap *aarp);
void xfs_alloc_commit_autoreap(struct xfs_trans *tp,
+8 −4
Original line number Diff line number Diff line
@@ -605,7 +605,7 @@ xfs_bmap_btree_to_extents(

	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
	error = xfs_free_extent_later(cur->bc_tp, cbno, 1, &oinfo,
			XFS_AG_RESV_NONE, false);
			XFS_AG_RESV_NONE, 0);
	if (error)
		return error;

@@ -5381,11 +5381,15 @@ xfs_bmap_del_extent_real(
			error = xfs_rtfree_blocks(tp, del->br_startblock,
					del->br_blockcount);
		} else {
			unsigned int	efi_flags = 0;

			if ((bflags & XFS_BMAPI_NODISCARD) ||
			    del->br_state == XFS_EXT_UNWRITTEN)
				efi_flags |= XFS_FREE_EXTENT_SKIP_DISCARD;

			error = xfs_free_extent_later(tp, del->br_startblock,
					del->br_blockcount, NULL,
					XFS_AG_RESV_NONE,
					((bflags & XFS_BMAPI_NODISCARD) ||
					del->br_state == XFS_EXT_UNWRITTEN));
					XFS_AG_RESV_NONE, efi_flags);
		}
		if (error)
			return error;
+1 −1
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ xfs_bmbt_free_block(

	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_ino.whichfork);
	error = xfs_free_extent_later(cur->bc_tp, fsbno, 1, &oinfo,
			XFS_AG_RESV_NONE, false);
			XFS_AG_RESV_NONE, 0);
	if (error)
		return error;

Loading