mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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: bd1d2c21d5 ("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>
This commit is contained in:
parent
0db22d7ee4
commit
8d54eacd82
|
|
@ -1130,7 +1130,7 @@ xfs_atomic_write_cow_iomap_begin(
|
|||
return -EAGAIN;
|
||||
|
||||
trace_xfs_iomap_atomic_write_cow(ip, offset, length);
|
||||
|
||||
retry:
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
|
||||
if (!ip->i_cowfp) {
|
||||
|
|
@ -1141,6 +1141,8 @@ xfs_atomic_write_cow_iomap_begin(
|
|||
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
|
||||
cmap.br_startoff = end_fsb;
|
||||
if (cmap.br_startoff <= offset_fsb) {
|
||||
if (isnullstartblock(cmap.br_startblock))
|
||||
goto convert_delay;
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
goto found;
|
||||
}
|
||||
|
|
@ -1169,8 +1171,10 @@ xfs_atomic_write_cow_iomap_begin(
|
|||
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
|
||||
cmap.br_startoff = end_fsb;
|
||||
if (cmap.br_startoff <= offset_fsb) {
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
xfs_trans_cancel(tp);
|
||||
if (isnullstartblock(cmap.br_startblock))
|
||||
goto convert_delay;
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
goto found;
|
||||
}
|
||||
|
||||
|
|
@ -1210,6 +1214,19 @@ xfs_atomic_write_cow_iomap_begin(
|
|||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags, IOMAP_F_SHARED, seq);
|
||||
|
||||
convert_delay:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
error = xfs_bmapi_convert_delalloc(ip, XFS_COW_FORK, offset, iomap,
|
||||
NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Try the lookup again, because the delalloc conversion might have
|
||||
* turned the COW mapping into unwritten, but we need it to be in
|
||||
* written state.
|
||||
*/
|
||||
goto retry;
|
||||
out_unlock:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
return error;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user