From: Mohamed Khalfella <mkhalfella@purestorage.com>
To: Jesse Taube <jtaubepe@redhat.com>
Cc: linux-block@vger.kernel.org, shinichiro.kawasaki@wdc.com,
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>,
Randy Jennings <randyj@purestorage.com>,
Dhaval Giani <dgiani@purestorage.com>
Subject: Re: [PATCH blktests 5/5] nvme/070: test for ABA ghost writes on a multipath fabrics namespace
Date: Wed, 23 Sep 2026 09:56:12 -0700 [thread overview]
Message-ID: <20260923165612.GF2931-mkhalfella@purestorage.com> (raw)
In-Reply-To: <CADRr4bffEXo-0sjyCWYsBmH01miQ9uURqLYXuBHPk0bnV2Apkg@mail.gmail.com>
On Tue 2026-09-22 13:07:04 -0400, Jesse Taube wrote:
> On Wed, Sep 16, 2026 at 10:09 PM Mohamed Khalfella
> <mkhalfella@purestorage.com> wrote:
> >
> > An unacknowledged write that is retried on another path can still be
> > alive in the fabric. If it reaches the target after a later write to the
> > same LBA has landed, it overwrites it, and a read returns stale data.
> > Nothing in the tree exercises that window.
> >
> > Add a test that builds it deliberately. A ublk loop device backs an
> > nvmet namespace exported through two ports, and the host connects to
> > both, so nvme-multipath has a second path to fail over to. io_timeout on
> > the subsystem drops to 2 seconds, then miniublk's inject command holds
> > one write in the backstore for 4 seconds. The host times that write out,
> > retries it on the other path, and the held write completes at the target
> > afterwards.
> >
> > nvme-ghost-write-detector then writes distinct patterns to a single LBA
> > and reads the block back, so a resurfaced write shows up as the wrong
> > pattern.
> >
> > The test requires nvme_core.multipath=Y and a fabrics transport. As of
> > today it passes on loop, which defines no timeout callback and so never
> > times the write out and never retries it, and fails on tcp, rdma and fc.
>
> Can you share a tcp or fc variant of this test that demonstrates failure?
Okay, will do that in next revision.
>
> >
> > Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
>
> Reviewed-by: Jesse Taube <jtaubepe@redhat.com>
> Tested-by: Jesse Taube <jtaubepe@redhat.com>
Thanks for testing and reviewing the change.
>
> > ---
> > tests/nvme/070 | 98 ++++++++++++++++++++++++++++++++++++++++++++++
> > tests/nvme/070.out | 35 +++++++++++++++++
> > 2 files changed, 133 insertions(+)
> > create mode 100755 tests/nvme/070
> > create mode 100644 tests/nvme/070.out
>
> btw this needs to be bumped to 071 as 070 got added recently.
Noted.
>
> Thanks,
> Jesse Taube
>
> >
> > diff --git a/tests/nvme/070 b/tests/nvme/070
> > new file mode 100755
> > index 0000000..e9a4690
> > --- /dev/null
> > +++ b/tests/nvme/070
> > @@ -0,0 +1,98 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-3.0+
> > +# Copyright (C) 2026 Mohamed Khalfella
> > +
> > +. tests/nvme/rc
> > +. common/ublk
> > +
> > +DESCRIPTION="Test injecting delay on nvme-target backstore and expect no corruption"
> > +
> > +requires() {
> > + _nvme_requires
> > + _have_loop
> > + _have_ublk
> > + _have_module_param_value nvme_core multipath Y
> > + _require_nvme_trtype_is_fabrics
> > + _have_src_program nvme-ghost-write-detector
> > +}
> > +
> > +set_conditions() {
> > + _set_nvme_trtype "$@"
> > +}
> > +
> > +count_paths_to_subsystem() {
> > + local subsysnqn="$1"
> > + local dev count
> > +
> > + count=0
> > + for dev in /sys/class/nvme/nvme*; do
> > + [[ -e "${dev}/subsysnqn" ]] || continue
> > + [[ "$(cat "${dev}/subsysnqn")" == "${subsysnqn}" ]] || continue
> > + count=$(( count + 1 ))
> > + done
> > + echo "${count}"
> > +}
> > +
> > +set_io_timeout_of_subsystem() {
> > + local subsysnqn="$1"
> > + local timeout="$2"
> > + local dev
> > +
> > + for dev in /sys/class/nvme/nvme*; do
> > + [[ -e "${dev}/subsysnqn" ]] || continue
> > + [[ "$(cat "${dev}/subsysnqn")" == "${subsysnqn}" ]] || continue
> > + if ! echo "${timeout}" > "${dev}/io_timeout" 2> /dev/null; then
> > + echo "FAIL: can not set io_timeout on ${dev##*/}"
> > + return 1
> > + fi
> > + done
> > +}
> > +
> > +test() {
> > + echo "Running ${TEST_NAME}"
> > +
> > + local ns port nr_paths
> > + local -a ports
> > +
> > + if ! _init_ublk; then
> > + return 1
> > + fi
> > +
> > + truncate -s "${NVME_IMG_SIZE}" "${TMPDIR}/ublk-img"
> > + if ! ${UBLK_PROG} add -t loop -f "${TMPDIR}/ublk-img" -n 0 > "$FULL" 2>&1; then
> > + echo "fail to add ublk device"
> > + _exit_ublk
> > + return 1
> > + fi
> > + udevadm settle
> > +
> > + _setup_nvmet
> > + _nvmet_target_setup --ports 2 --blkdev none
> > + _create_nvmet_ns --blkdev /dev/ublkb0 \
> > + --uuid "${def_subsys_uuid}" > /dev/null
> > +
> > + _get_nvmet_ports "${def_subsysnqn}" ports
> > + echo "Target ports: ${#ports[@]}"
> > + for port in "${ports[@]}"; do
> > + _nvme_connect_subsys --port "${port}"
> > + done
> > +
> > + nr_paths=$(count_paths_to_subsystem "${def_subsysnqn}")
> > + if (( nr_paths != 2 )); then
> > + echo "FAIL: expected 2 paths, found ${nr_paths}"
> > + fi
> > +
> > + 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
> > +
> > + ns=$(_find_nvme_ns "${def_subsys_uuid}")
> > + "$SRCDIR/nvme-ghost-write-detector" "/dev/${ns}"
> > +
> > + _nvme_disconnect_subsys
> > + _nvmet_target_cleanup
> > + _exit_ublk
> > + echo "Test complete"
> > +}
> > diff --git a/tests/nvme/070.out b/tests/nvme/070.out
> > new file mode 100644
> > index 0000000..b43fec7
> > --- /dev/null
> > +++ b/tests/nvme/070.out
> > @@ -0,0 +1,35 @@
> > +Running nvme/070
> > +Target ports: 2
> > +starting nvme-ghost-write-detector test program
> > +iteration number 0, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 1, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 2, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 3, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 4, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 5, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 6, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 7, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 8, writing data
> > +validating written data
> > +successfully validated
> > +iteration number 9, writing data
> > +validating written data
> > +successfully validated
> > +finished nvme-ghost-write-detector test program
> > +Test complete
> > --
> > 2.55.0
> >
>
next prev parent reply other threads:[~2026-09-23 16:56 UTC|newest]
Thread overview: 13+ 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 [this message]
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
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=20260923165612.GF2931-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox