[PATCH v5 04/10] xfs: Reflink CoW-based atomic write support

From: John Garry
Date: Mon Mar 10 2025 - 14:41:35 EST


Base SW-based atomic writes on CoW.

For SW-based atomic write support, always allocate a cow hole in
xfs_reflink_allocate_cow() to write the new data.

The semantics is that if @atomic_sw is set, we will be passed a CoW fork
extent mapping for no error returned.

Reviewed-by: "Darrick J. Wong" <djwong@xxxxxxxxxx>
Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx>
---
fs/xfs/xfs_reflink.c | 5 +++--
fs/xfs/xfs_reflink.h | 1 +
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index e3e594c65745..0949d6ba2b3b 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -444,6 +444,7 @@ xfs_reflink_fill_cow_hole(
int nimaps;
int error;
bool found;
+ bool atomic_sw = flags & XFS_REFLINK_ATOMIC_SW;

resaligned = xfs_aligned_fsb_count(imap->br_startoff,
imap->br_blockcount, xfs_get_cowextsz_hint(ip));
@@ -466,7 +467,7 @@ xfs_reflink_fill_cow_hole(
*lockmode = XFS_ILOCK_EXCL;

error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found);
- if (error || !*shared)
+ if (error || (!*shared && !atomic_sw))
goto out_trans_cancel;

if (found) {
@@ -580,7 +581,7 @@ xfs_reflink_allocate_cow(
}

error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found);
- if (error || !*shared)
+ if (error || (!*shared && !(flags & XFS_REFLINK_ATOMIC_SW)))
return error;

/* CoW fork has a real extent */
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index cdbd73d58822..dfd94e51e2b4 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -10,6 +10,7 @@
* Flags for xfs_reflink_allocate_cow()
*/
#define XFS_REFLINK_CONVERT (1u << 0) /* convert unwritten extents now */
+#define XFS_REFLINK_ATOMIC_SW (1u << 1) /* alloc for SW-based atomic write */

/*
* Check whether it is safe to free COW fork blocks from an inode. It is unsafe
--
2.31.1