Linux XFS filesystem development
 help / color / mirror / Atom feed
From: Dave Chinner <dgc@kernel.org>
To: linux-xfs@vger.kernel.org
Cc: cem@kernel.org
Subject: [PATCH 03/33] xfs: fix block reservation for zoned RT extent remapping
Date: Wed, 29 Jul 2026 20:01:47 +1000	[thread overview]
Message-ID: <20260729100629.1943710-4-dgc@kernel.org> (raw)
In-Reply-To: <20260729100629.1943710-1-dgc@kernel.org>

xfs_zoned_end_io() uses XFS_EXTENTADD_SPACE_RES() for its block
reservation, which only covers bmbt splits. However, the remap
operation in xfs_zoned_map_extent() generates deferred rmap and
refcount btree updates that also need blocks for btree splits
when they are processed.

The code used XFS_TRANS_RES_FDBLKS as a workaround to recycle
freed data blocks back into the transaction's block reservation.
This is fragile — it depends on freed blocks being large enough
to cover the metadata btree needs, and conflates data block
recycling with metadata reservation.

Fix this by introducing XFS_RTEXTENTADD_SPACE_RES() which computes
the correct reservation for any RT data extent modification: the
bmbt split cost plus the rt rmap btree split cost plus the rt
refcount btree cost. This covers all the deferred operations that
are generated when an RT extent is mapped or unmapped.

Drop XFS_TRANS_RES_FDBLKS from xfs_zoned_end_io() since the
reservation now correctly covers all btree costs.

Note: XFS_RTEXTENTADD_SPACE_RES() should eventually be folded
into XFS_EXTENTADD_SPACE_RES() so that all callers operating on
RT inodes automatically get the correct reservation. There are
approximately 11 sites that use XFS_EXTENTADD_SPACE_RES either
directly or via XFS_DIOSTRAT_SPACE_RES that have the same
under-reservation issue for RT inodes.

Fixes: 4e4d52075577 ("xfs: add the zoned space allocator")
Assisted-by: LLM
Signed-off-by: Dave Chinner <dgc@kernel.org>
---
 fs/xfs/libxfs/xfs_trans_space.h | 12 ++++++++++++
 fs/xfs/xfs_zone_alloc.c         |  5 ++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index d89b570aafcc..4cfc29ac764f 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -55,6 +55,18 @@
 	  XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
 	  XFS_EXTENTADD_SPACE_RES(mp,w))
 
+/*
+ * Blocks needed to add or remove a realtime data extent: the bmbt split plus
+ * rt rmap btree and rt refcount btree updates deferred from the bmbt operation.
+ *
+ * TODO: this should be folded into XFS_EXTENTADD_SPACE_RES() so that all
+ * callers that operate on RT inodes automatically get the correct reservation.
+ */
+#define XFS_RTEXTENTADD_SPACE_RES(mp)	\
+	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
+	 (xfs_has_rmapbt(mp) ? XFS_RTRMAPADD_SPACE_RES(mp) : 0) + \
+	 (xfs_has_reflink(mp) ? 2 * (mp)->m_rtrefc_maxlevels - 1 : 0))
+
 /* Blocks we might need to add "b" mappings & rmappings to a file. */
 #define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
 	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w)) + \
diff --git a/fs/xfs/xfs_zone_alloc.c b/fs/xfs/xfs_zone_alloc.c
index 7d13fa7ab30a..7e3456ca28ac 100644
--- a/fs/xfs/xfs_zone_alloc.c
+++ b/fs/xfs/xfs_zone_alloc.c
@@ -330,8 +330,7 @@ xfs_zoned_end_io(
 		.br_startblock	= xfs_daddr_to_rtb(mp, daddr),
 		.br_state	= XFS_EXT_NORM,
 	};
-	unsigned int		resblks =
-		XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
+	unsigned int		resblks = XFS_RTEXTENTADD_SPACE_RES(mp);
 	struct xfs_trans	*tp;
 	int			error;
 
@@ -342,7 +341,7 @@ xfs_zoned_end_io(
 		new.br_blockcount = end_fsb - new.br_startoff;
 
 		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
-				XFS_TRANS_RESERVE | XFS_TRANS_RES_FDBLKS, &tp);
+				XFS_TRANS_RESERVE, &tp);
 		if (error)
 			return error;
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
-- 
2.55.0


  parent reply	other threads:[~2026-07-29 10:06 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-29 10:01 [RFC PATCH 00/33] XFS: Atomic multi-extent operations via rolling transactions Dave Chinner
2026-07-29 10:01 ` [PATCH 01/33] xfs: fix dirty transaction cancellation in xfs_bmapi_convert_one_delalloc Dave Chinner
2026-07-29 10:01 ` [PATCH 02/33] xfs: fix isize update in xfs_iomap_write_unwritten to track conversion progress Dave Chinner
2026-07-29 10:01 ` Dave Chinner [this message]
2026-07-29 10:01 ` [PATCH 04/33] xfs: factor out COW iomap handling from xfs_direct_write_iomap_begin() Dave Chinner
2026-07-29 10:01 ` [PATCH 05/33] xfs: plumb xfs_trans through xfs_reflink_allocate_cow and fill_cow_hole Dave Chinner
2026-07-29 10:01 ` [PATCH 06/33] xfs: teach xfs_reflink_fill_cow_hole() to use a caller-supplied transaction Dave Chinner
2026-07-29 10:01 ` [PATCH 07/33] xfs: add transaction retry infrastructure to xfs_direct_write_cow_iomap_begin Dave Chinner
2026-07-29 10:01 ` [PATCH 08/33] xfs: return -EAGAIN from xfs_reflink_allocate_cow for COW hole without transaction Dave Chinner
2026-07-29 10:01 ` [PATCH 09/33] xfs: remove internal transaction allocation from xfs_reflink_fill_cow_hole Dave Chinner
2026-07-29 10:01 ` [PATCH 10/33] xfs: use zero-block transaction with xfs_trans_reserve_more_inode for COW holes Dave Chinner
2026-07-29 10:01 ` [PATCH 11/33] xfs: change *tp to **tpp in COW allocation call chain Dave Chinner
2026-07-29 10:01 ` [PATCH 12/33] xfs: convert xfs_reflink_fill_delalloc to use rolling transactions Dave Chinner
2026-07-29 10:01 ` [PATCH 13/33] xfs: return -EAGAIN from xfs_reflink_allocate_cow for all allocation cases Dave Chinner
2026-07-29 10:01 ` [PATCH 14/33] xfs: remove dead internal transaction allocation from xfs_reflink_fill_delalloc Dave Chinner
2026-07-29 10:01 ` [PATCH 15/33] xfs: plumb struct xfs_trans *tp into xfs_bmapi_convert_one_delalloc Dave Chinner
2026-07-29 10:02 ` [PATCH 16/33] xfs: use rolling transaction in xfs_bmapi_convert_delalloc Dave Chinner
2026-07-29 10:02 ` [PATCH 17/33] xfs: remove dead internal transaction path from xfs_bmapi_convert_one_delalloc Dave Chinner
2026-07-29 10:02 ` [PATCH 18/33] xfs: add block reservation renewal to xfs_defer_finish Dave Chinner
2026-07-29 10:02 ` [PATCH 19/33] xfs: factor out xfs_iomap_write_unwritten_one helper Dave Chinner
2026-07-29 10:02 ` [PATCH 20/33] xfs: convert xfs_iomap_write_unwritten to rolling transactions Dave Chinner
2026-07-29 10:02 ` [PATCH 21/33] xfs: plumb struct xfs_trans *tp into xfs_reflink_end_cow_extent Dave Chinner
2026-07-29 10:02 ` [PATCH 22/33] xfs: convert xfs_reflink_end_cow to rolling transactions Dave Chinner
2026-07-29 10:02 ` [PATCH 23/33] xfs: remove xfs_reflink_end_cow_extent wrapper and rename locked variant Dave Chinner
2026-07-29 10:02 ` [PATCH 24/33] xfs: convert xfs_zoned_end_io to rolling transactions Dave Chinner
2026-07-29 10:02 ` [PATCH 25/33] xfs: plumb struct xfs_trans *tp into xfs_iomap_write_direct Dave Chinner
2026-07-29 10:02 ` [PATCH 26/33] xfs: make xfs_iomap_write_direct fill in the iomap directly Dave Chinner
2026-07-29 10:02 ` [PATCH 27/33] xfs: plumb struct xfs_trans **tpp into xfs_direct_write_cow_iomap_begin Dave Chinner
2026-07-29 10:02 ` [PATCH 28/33] xfs: introduce struct xfs_direct_write_args for direct write call chain Dave Chinner
2026-07-29 10:02 ` [PATCH 29/33] xfs: convert xfs_direct_write_iomap_begin to use dwa struct throughout Dave Chinner
2026-07-29 10:02 ` [PATCH 30/33] xfs: restructure xfs_direct_write_iomap_begin with unified retry loop Dave Chinner
2026-07-29 10:02 ` [PATCH 31/33] xfs: clean up xfs_direct_write_cow_iomap_begin after restructure Dave Chinner
2026-07-29 10:02 ` [PATCH 32/33] xfs: make pNFS block allocation atomic with inode update Dave Chinner
2026-07-29 10:02 ` [PATCH 33/33] xfs: remove dead internal transaction path from xfs_iomap_write_direct Dave Chinner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260729100629.1943710-4-dgc@kernel.org \
    --to=dgc@kernel.org \
    --cc=cem@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox