Skip to content

Commit 8d54eac

Browse files
Darrick J. Wongcmaiolino
authored andcommitted
xfs: fix delalloc write failures in software-provided atomic writes
With the 20 Oct 2025 release of fstests, generic/521 fails for me on regular (aka non-block-atomic-writes) storage: QA output created by 521 dowrite: write: Input/output error LOG DUMP (8553 total operations): 1( 1 mod 256): SKIPPED (no operation) 2( 2 mod 256): WRITE 0x7e000 thru 0x8dfff (0x10000 bytes) HOLE 3( 3 mod 256): READ 0x69000 thru 0x79fff (0x11000 bytes) 4( 4 mod 256): FALLOC 0x53c38 thru 0x5e853 (0xac1b bytes) INTERIOR 5( 5 mod 256): COPY 0x55000 thru 0x59fff (0x5000 bytes) to 0x25000 thru 0x29fff 6( 6 mod 256): WRITE 0x74000 thru 0x88fff (0x15000 bytes) 7( 7 mod 256): ZERO 0xedb1 thru 0x11693 (0x28e3 bytes) with a warning in dmesg from iomap about XFS trying to give it a delalloc mapping for a directio write. Fix the software atomic write iomap_begin code to convert the reservation into a written mapping. This doesn't fix the data corruption problems reported by generic/760, but it's a start. Cc: stable@vger.kernel.org # v6.16 Fixes: bd1d2c2 ("xfs: add xfs_atomic_write_cow_iomap_begin()") Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: John Garry <john.g.garry@oracle.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent 0db22d7 commit 8d54eac

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

fs/xfs/xfs_iomap.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ xfs_atomic_write_cow_iomap_begin(
11301130
return -EAGAIN;
11311131

11321132
trace_xfs_iomap_atomic_write_cow(ip, offset, length);
1133-
1133+
retry:
11341134
xfs_ilock(ip, XFS_ILOCK_EXCL);
11351135

11361136
if (!ip->i_cowfp) {
@@ -1141,6 +1141,8 @@ xfs_atomic_write_cow_iomap_begin(
11411141
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
11421142
cmap.br_startoff = end_fsb;
11431143
if (cmap.br_startoff <= offset_fsb) {
1144+
if (isnullstartblock(cmap.br_startblock))
1145+
goto convert_delay;
11441146
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11451147
goto found;
11461148
}
@@ -1169,8 +1171,10 @@ xfs_atomic_write_cow_iomap_begin(
11691171
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
11701172
cmap.br_startoff = end_fsb;
11711173
if (cmap.br_startoff <= offset_fsb) {
1172-
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11731174
xfs_trans_cancel(tp);
1175+
if (isnullstartblock(cmap.br_startblock))
1176+
goto convert_delay;
1177+
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11741178
goto found;
11751179
}
11761180

@@ -1210,6 +1214,19 @@ xfs_atomic_write_cow_iomap_begin(
12101214
xfs_iunlock(ip, XFS_ILOCK_EXCL);
12111215
return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags, IOMAP_F_SHARED, seq);
12121216

1217+
convert_delay:
1218+
xfs_iunlock(ip, XFS_ILOCK_EXCL);
1219+
error = xfs_bmapi_convert_delalloc(ip, XFS_COW_FORK, offset, iomap,
1220+
NULL);
1221+
if (error)
1222+
return error;
1223+
1224+
/*
1225+
* Try the lookup again, because the delalloc conversion might have
1226+
* turned the COW mapping into unwritten, but we need it to be in
1227+
* written state.
1228+
*/
1229+
goto retry;
12131230
out_unlock:
12141231
xfs_iunlock(ip, XFS_ILOCK_EXCL);
12151232
return error;

0 commit comments

Comments
 (0)