From: Daejun Park For a bio with REQ_PREFLUSH and data, dm core may send an empty flush first. If the flush fails, __dm_io_complete() still reissues the bio without REQ_PREFLUSH and drops the error. When that write succeeds, the XFS log keeps running and fsync() can return 0. End the bio with the flush error instead of writing the data, as blk-mq does. Fixes: 6a8736d10cb4 ("dm: relax ordering of bio-based flush implementation") Cc: stable@vger.kernel.org Signed-off-by: Daejun Park --- Tested on v7.4-rc2: XFS on a two-device linear table whose second device (dm-flakey, no data) fails every flush. Before, 200 of 200 fsyncs of one writer return 0. After, the log write fails with -EIO and XFS shuts down. Kernels before v6.18 have a different condition here and need a separate backport. fstests xfs/438 uses dm-flakey targets around a linear target for the log to fail writes. dm-flakey fails the flush clones too. With this patch, XFS shuts down on the first log write with REQ_PREFLUSH after the errors start, before a metadata write fails. The test still passes. A series for fstests moves xfs/438 to the buf_ioerror error tag. --- drivers/md/dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 1881d86111f..0f6934e0008 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -983,7 +983,7 @@ static void __dm_io_complete(struct dm_io *io, bool first_stage) if (requeued) return; - if (unlikely(requeue_flush_with_data)) { + if (unlikely(requeue_flush_with_data) && !io_error) { /* * Preflush done for flush with data, reissue * without REQ_PREFLUSH. @@ -991,7 +991,7 @@ static void __dm_io_complete(struct dm_io *io, bool first_stage) bio->bi_opf &= ~REQ_PREFLUSH; queue_io(md, bio); } else { - /* done with normal IO or empty flush */ + /* done with normal IO, empty flush or failed preflush */ if (io_error) bio->bi_status = io_error; bio_endio(bio); --- base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb change-id: 20261111-dm-flush-data-error-5687385d8c0c Best regards, -- Daejun Park