mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] block: keep flush error across tag iterator reference drops
@ 2026-10-20 19:04 Nirmoy Das
  0 siblings, 0 replies; only message in thread
From: Nirmoy Das @ 2026-10-20 19:04 UTC (permalink / raw)
  To: axboe
  Cc: tom.leiming, yuyufen, bob.liu, yebin, linux-block, linux-kernel,
	Nirmoy Das, stable

Tag iterators such as blk_mq_queue_tag_busy_iter() take a reference on
each busy request, the flush request included, and drop it with
blk_mq_put_rq_ref(). For the flush request that calls flush_end_io()
with a zero status. When that put is not the last one, flush_end_io()
stores the status in fq->rq_status for the last put to report, so the
iterator's zero overwrites an error the device completion stored there.

With two iterators holding references, the device completes the flush
with an error and flush_end_io() stores it, the first iterator drops
its reference and stores 0, and the second drop reports success. The
requests waiting on the flush complete without the error and fsync()
returns 0.

Only store a nonzero status in fq->rq_status, so dropping an iterator
reference can't clear an error.

Reproduced on v7.3 in an x86 QEMU guest with scsi_debug, failing every
SYNCHRONIZE CACHE through its debugfs error injection while 16
processes read /sys/block/sda/inflight:

  modprobe scsi_debug dev_size_mb=64 ndelay=100000
  echo "2 1 0x35 0x00 0x00 0x02 0x04 0x44 0x00" > \
      /sys/kernel/debug/scsi_debug/<h:c:t:l>/error

fsync() returned 0 for 35 of 18000 calls on /dev/sda and for 46 of 18000
calls on a file on ext4 without a journal, over six runs. With this
change every call failed.

Fixes: 8d6996630c03 ("block: fix null pointer dereference in blk_mq_rq_timed_out()")
Cc: stable@vger.kernel.org
Assisted-by: LLM Specula
Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
---
Ye Bin's "blk-flush: fix possibe deadlock when process nvme_timeout()"
(not merged yet) adds lines right after the same assignment, so the
second of the two to be applied needs a trivial rebase.

 block/blk-flush.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block/blk-flush.c b/block/blk-flush.c
index 403a46c8641172d..65697e2efad290b 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -212,7 +212,8 @@ static enum rq_end_io_ret flush_end_io(struct request *flush_rq,
 	spin_lock_irqsave(&fq->mq_flush_lock, flags);
 
 	if (!req_ref_put_and_test(flush_rq)) {
-		fq->rq_status = error;
+		if (error)
+			fq->rq_status = error;
 		spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 		return RQ_END_IO_NONE;
 	}
-- 
2.43.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-20 19:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-20 19:04 [PATCH] block: keep flush error across tag iterator reference drops Nirmoy Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®