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 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.