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 3b1b7a56af34..97dc38841063 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