[PATCH 08/33] xfs: return -EAGAIN from xfs_reflink_allocate_cow for COW hole without transaction
Dave Chinner <[email protected]> Wed, 29 Jul 2026 20:01:52 +1000
| Newsgroups | org.kernel.vger.linux-xfs |
|---|---|
| Message-ID | <[email protected]> |
When xfs_reflink_allocate_cow() encounters a COW fork hole that needs a real extent allocated and no transaction has been provided, return -EAGAIN to tell the caller to allocate a transaction and retry. When a transaction is provided, pass it through to xfs_reflink_fill_cow_hole() which will use it directly for the COW extent allocation without needing to cycle the ILOCK. This activates the retry loop added in the previous patch: on the first call (tp == NULL), allocate_cow returns -EAGAIN, the caller drops the ILOCK, allocates a transaction, and retries. On the second call (tp != NULL), the transaction is passed down to fill_cow_hole() and the COW allocation completes atomically under the ILOCK without cycling it. Assisted-by: LLM Signed-off-by: Dave Chinner <[email protected]> --- fs/xfs/xfs_reflink.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 1ad0569ecdd1..56ad76b0f6b9 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -643,16 +643,22 @@ xfs_reflink_allocate_cow( /* * CoW fork does not have an extent and data extent is shared. - * Allocate a real extent in the CoW fork. + * Allocate a real extent in the CoW fork. If the caller has not + * provided a transaction for the allocation, return -EAGAIN to + * tell the caller to allocate a transaction and retry. */ - if (cmap->br_startoff > imap->br_startoff) - return xfs_reflink_fill_cow_hole(NULL, ip, imap, cmap, shared, + if (cmap->br_startoff > imap->br_startoff) { + if (!tp) + return -EAGAIN; + return xfs_reflink_fill_cow_hole(tp, ip, imap, cmap, shared, lockmode, convert_now); + } /* * CoW fork has a delalloc reservation. Replace it with a real extent. * There may or may not be a data fork mapping. */ + ASSERT(!tp); if (isnullstartblock(cmap->br_startblock) || cmap->br_startblock == DELAYSTARTBLOCK) return xfs_reflink_fill_delalloc(ip, imap, cmap, shared, -- 2.55.0