All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mohamed Khalfella <mkhalfella@purestorage.com>
To: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Cc: linux-block@vger.kernel.org, Keith Busch <kbusch@kernel.org>,
	Jens Axboe <axboe@kernel.dk>, Christoph Hellwig <hch@lst.de>,
	Sagi Grimberg <sagi@grimberg.me>, Hannes Reinecke <hare@suse.de>,
	John Meneghini <jmeneghi@redhat.com>,
	Jesse Taube <jtaubepe@redhat.com>,
	Randy Jennings <randyj@purestorage.com>,
	Dhaval Giani <dgiani@purestorage.com>
Subject: Re: [PATCH blktests 0/5] nvme: detect ABA ghost writes on multipath fabrics
Date: Thu, 22 Oct 2026 11:59:20 -0700	[thread overview]
Message-ID: <20261022185920.GA2931-mkhalfella@purestorage.com> (raw)
In-Reply-To: <20261020180245.GP2931-mkhalfella@purestorage.com>

On Tue 2026-10-20 11:02:47 -0700, Mohamed Khalfella wrote:
> On Fri 2026-10-02 05:03:20 +0200, Shin'ichiro Kawasaki wrote:
> > On Sep 23, 2026 / 10:02, Mohamed Khalfella wrote:
> > > On Wed 2026-09-23 17:18:21 +0900, Shin'ichiro Kawasaki wrote:
> > > > On Sep 16, 2026 / 20:06, Mohamed Khalfella wrote:
> > > > 
> > > > Mohamad, thanks for the series. Before I look in the details of the patches,
> > > > I would like make a comment below.
> > > > 
> > > > > Reproducing the race needs an IO that can be held at the target for
> > > > > longer than the host's io_timeout without being failed. The first three
> > > > > patches give miniublk that ability, since there was previously no way to
> > > > > talk to a running ublk server at all:
> > > > > 
> > > > >   1/5  adds a loopback UDP control channel to the daemon, served by a
> > > > >        detached thread, one reply datagram per request
> > > > >   2/5  adds an INJECT_DELAY command which delays a given number of reads
> > > > >        or writes as an io_uring timeout on the queue's own ring
> > > > >   3/5  exposes it as "miniublk inject", which returns only once the
> > > > >        daemon has armed the delay, so a test can start IO immediately
> > > > >        without racing it
> > > > 
> > > > It is interesting to implement the delay feature to miniublk, and use it as the
> > > > testing tool. But I'm not sure if this is the best approach because of two
> > > > points. First, scsi_debug has jdelay and ndelay options. I wonder if this
> > > > existing feature can fulfill the requirements of the new test case. Second, when
> > > > rublk [*] is available in the PATH of the test system, blktests detect it and
> > > > use it instead of miniublk. I guess the added delay feature is not available in
> > > > rublk, and the test case won't work well. What do you think of these points?
> > > > 
> > > 
> > > The two points make sense to me. Let me look at scsi_debug delay
> > > injection mechanism first and see if it can be used here. I will also
> > > look at rublk. Thanks for the pointers.
> > 
> > I've learned that now delay injection is being added to the block layer [*].
> > This looks more generic and could be the best way for this use case.
> > 
> > [*] https://lore.kernel.org/linux-block/20260928221634.43239-1-haris.iqbal@linux.dev/
> 
> Thank you for pointing me to this patchset. The change as in v3 in the
> link above is not sufficient for this case. Block layer "error_inject"
> does not support an option to set the maximum number of times a rule
> should be executed. I want only the first write to be delayed for the
> test to be deterministic.
> 
> That is said, it should not be difficult to close this gap. I will give
> it a shot.

Adding a limit to error injection rule worked.

[ 1244.485435] run blktests nvme/070 at 2026-10-22 11:40:52.361981983
[ 1245.355103] nvmet_tcp: enabling port 0 (127.0.0.1:4420)
[ 1245.401761] nvmet_tcp: enabling port 1 (127.0.0.1:4421)
[ 1245.443655] nvmet: adding nsid 1 to subsystem blktests-subsystem-1
[ 1245.579679] nvmet: Created nvm controller 1 for subsystem blktests-subsystem-1 for NQN nqn.2014-08.org.nvmexpress:uui.
[ 1245.587802] nvme nvme4: creating 8 I/O queues.
[ 1245.599665] nvme nvme4: mapped 8/0/0 default/read/poll queues.
[ 1245.612520] nvme nvme4: new ctrl: NQN "blktests-subsystem-1", addr 127.0.0.1:4420, hostnqn: nqn.2014-08.org.nvmexpres9
[ 1245.993765] nvmet: Created nvm controller 2 for subsystem blktests-subsystem-1 for NQN nqn.2014-08.org.nvmexpress:uui.
[ 1246.001615] nvme nvme5: creating 8 I/O queues.
[ 1246.016800] nvme nvme5: mapped 8/0/0 default/read/poll queues.
[ 1246.031323] nvme nvme5: new ctrl: NQN "blktests-subsystem-1", addr 127.0.0.1:4421, hostnqn: nqn.2014-08.org.nvmexpres9
[ 1246.561862] ublkb0: delaying WRITE at sector 0:8 by 4000000us
[ 1249.908509] nvme nvme4: I/O tag 81 (0051) type 4 opcode 0x1 (Write) QID 7 timeout
[ 1249.910523] nvme nvme4: starting controller fencing
[ 1249.911588] nvme nvme4: attempting CCR, timeout 15000ms
[ 1249.913245] nvmet: ctrl 1 fatal error occurred!
[ 1250.631188] nvme nvme4: CCR succeeded using nvme5
[ 1250.647822] nvme nvme4: Reconnecting in 10 seconds...
[ 1260.710957] nvmet: Created nvm controller 1 for subsystem blktests-subsystem-1 for NQN nqn.2014-08.org.nvmexpress:uui.
[ 1260.718851] nvme nvme4: creating 8 I/O queues.
[ 1260.793810] nvme nvme4: mapped 8/0/0 default/read/poll queues.
[ 1260.805832] nvme nvme4: Successfully reconnected (attempt 1/60)
[ 1330.829938] nvme nvme5: Removing ctrl: NQN "blktests-subsystem-1"
[ 1331.316251] nvme nvme4: Removing ctrl: NQN "blktests-subsystem-1"

This full kernel logs for the test run with block layer delay injection.
A delay of 4 second injected -> io_timeout -> CCR.

diff --git a/tests/nvme/070 b/tests/nvme/070
index e9a4690..85604e7 100755
--- a/tests/nvme/070
+++ b/tests/nvme/070
@@ -51,7 +51,7 @@ set_io_timeout_of_subsystem() {
 test() {
        echo "Running ${TEST_NAME}"

-       local ns port nr_paths
+       local ns port nr_paths einj
        local -a ports

        if ! _init_ublk; then
@@ -84,9 +84,8 @@ test() {

        set_io_timeout_of_subsystem "${def_subsysnqn}" 2000

-       if ! ${UBLK_PROG} inject -n 0 -o write -d 4 -c 1 >> "$FULL" 2>&1; then
-               echo "FAIL: can not inject write delay"
-       fi
+       einj="/sys/kernel/debug/block/ublkb0/error_injection"
+       echo 'add,op=WRITE,status=OK,chance=1,delay_us=4000000,limit=1' > "${einj}"

        ns=$(_find_nvme_ns "${def_subsys_uuid}")
        "$SRCDIR/nvme-ghost-write-detector" "/dev/${ns}"

Changes to the test to use block layer error injection.

diff --git a/block/error-injection.c b/block/error-injection.c
index a35fe41a43e4..4d0150958cff 100644
--- a/block/error-injection.c
+++ b/block/error-injection.c
@@ -29,6 +29,9 @@ struct blk_error_inject {
 
 	/* hold the bio for this long before submitting or failing it */
 	unsigned int			delay_us;
+
+	/* maximum number of times to execute the rule, -1 no limit */
+	atomic_t			limit;
 };
 
 /*
@@ -143,6 +146,8 @@ bool __blk_error_inject(struct bio *bio)
 		if (inj->chance > 1 && (get_random_u32() % inj->chance) != 0)
 			continue;
 
+		if (atomic_dec_if_positive(&inj->limit) == -1)
+			continue;
 		status = inj->status;
 		delay_us = inj->delay_us;
 		break;
@@ -165,7 +170,7 @@ bool __blk_error_inject(struct bio *bio)
 
 static int error_inject_add(struct gendisk *disk, enum req_op op,
 		sector_t start, u64 nr_sectors, blk_status_t status,
-		unsigned int chance, unsigned int delay_us)
+		unsigned int chance, unsigned int delay_us, int limit)
 {
 	struct blk_error_inject *inj;
 	int error = -EINVAL;
@@ -194,6 +199,7 @@ static int error_inject_add(struct gendisk *disk, enum req_op op,
 	inj->status = status;
 	inj->chance = chance;
 	inj->delay_us = delay_us;
+	atomic_set(&inj->limit, limit);
 
 	pr_debug_ratelimited("%pg: adding %s injection for %s at sector %llu:%llu\n",
 			disk->part0, blk_status_to_str(status),
@@ -248,6 +254,7 @@ enum options {
 	Opt_status		= (1u << 19),
 	Opt_chance		= (1u << 20),
 	Opt_delay_us		= (1u << 21),
+	Opt_limit		= (1u << 22),
 
 	Opt_invalid,
 };
@@ -261,6 +268,7 @@ static const match_table_t opt_tokens = {
 	{ Opt_status,			"status=%s"		},
 	{ Opt_chance,			"chance=%u"		},
 	{ Opt_delay_us,			"delay_us=%u"		},
+	{ Opt_limit,			"limit=%d"		},
 	{ Opt_invalid,			NULL,			},
 };
 
@@ -302,6 +310,7 @@ static ssize_t blk_error_injection_parse_options(struct gendisk *disk,
 	u64 start = 0, nr_sectors = 0;
 	blk_status_t status = BLK_STS_OK;
 	substring_t args[MAX_OPT_ARGS];
+	int limit = -1;
 	char *p;
 
 	while ((p = strsep(&options, ",\n")) != NULL) {
@@ -343,6 +352,9 @@ static ssize_t blk_error_injection_parse_options(struct gendisk *disk,
 		case Opt_delay_us:
 			error = match_uint(args, &delay_us);
 			break;
+		case Opt_limit:
+			error = match_int(args, &limit);
+			break;
 		default:
 			pr_warn("unknown parameter or missing value '%s'\n", p);
 			error = -EINVAL;
@@ -354,7 +366,7 @@ static ssize_t blk_error_injection_parse_options(struct gendisk *disk,
 	switch (action) {
 	case Add:
 		return error_inject_add(disk, op, start, nr_sectors, status,
-				chance, delay_us);
+				chance, delay_us, limit);
 	case Removeall:
 		if (option_mask & ~Opt_removeall)
 			return -EINVAL;
@@ -390,11 +402,11 @@ static int blk_error_injection_show(struct seq_file *s, void *private)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(inj, &disk->error_injection_list, entry) {
-		seq_printf(s, "%llu:%llu op=%s,status=%s,chance=%u,delay_us=%u",
+		seq_printf(s, "%llu:%llu op=%s,status=%s,chance=%u,delay_us=%u,limit=%d",
 			   inj->start, inj->end,
 			   blk_op_str(inj->op),
 			   blk_status_to_tag(inj->status), inj->chance,
-			   inj->delay_us);
+			   inj->delay_us, atomic_read(&inj->limit));
 		seq_putc(s, '\n');
 	}
 	rcu_read_unlock();

And here is the change to block error injection to add a limit to error
injection rules. It missing documentation change but that should be
trivial to add.

Now, I need to follow with the patchset adding delay injection to see if
that can get merged.

      reply	other threads:[~2026-10-22 18:59 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-17  2:06 [PATCH blktests 0/5] nvme: detect ABA ghost writes on multipath fabrics Mohamed Khalfella
2026-09-17  2:06 ` [PATCH blktests 1/5] src/miniublk: add a control channel to the daemon Mohamed Khalfella
2026-09-17  2:06 ` [PATCH blktests 2/5] src/miniublk: add IO delay injection Mohamed Khalfella
2026-09-17  2:06 ` [PATCH blktests 3/5] src/miniublk: add the inject command Mohamed Khalfella
2026-09-17  2:06 ` [PATCH blktests 4/5] src/nvme-ghost-write-detector: add an ABA ghost write detector Mohamed Khalfella
2026-09-21 18:38   ` Jesse Taube
2026-09-23 17:00     ` Mohamed Khalfella
2026-09-17  2:06 ` [PATCH blktests 5/5] nvme/070: test for ABA ghost writes on a multipath fabrics namespace Mohamed Khalfella
2026-09-22 17:07   ` Jesse Taube
2026-09-23 16:56     ` Mohamed Khalfella
2026-09-23  8:18 ` [PATCH blktests 0/5] nvme: detect ABA ghost writes on multipath fabrics Shin'ichiro Kawasaki
2026-09-23 17:02   ` Mohamed Khalfella
2026-10-02  3:03     ` Shin'ichiro Kawasaki
2026-10-20 18:02       ` Mohamed Khalfella
2026-10-22 18:59         ` Mohamed Khalfella [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261022185920.GA2931-mkhalfella@purestorage.com \
    --to=mkhalfella@purestorage.com \
    --cc=axboe@kernel.dk \
    --cc=dgiani@purestorage.com \
    --cc=hare@suse.de \
    --cc=hch@lst.de \
    --cc=jmeneghi@redhat.com \
    --cc=jtaubepe@redhat.com \
    --cc=kbusch@kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=randyj@purestorage.com \
    --cc=sagi@grimberg.me \
    --cc=shinichiro.kawasaki@wdc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.