Linux block layer
 help / color / mirror / Atom feed
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 4/5] src/nvme-ghost-write-detector: add an ABA ghost write detector
Date: Wed, 23 Sep 2026 10:00:23 -0700	[thread overview]
Message-ID: <20260923170023.GG2931-mkhalfella@purestorage.com> (raw)
In-Reply-To: <CADRr4bdUDLcrV62TXimdhsXZ0GU=DPrBOXFJRix7BADw34TT7g@mail.gmail.com>

On Mon 2026-09-21 14:38:12 -0400, Jesse Taube wrote:
> On Wed, Sep 16, 2026 at 10:09 PM Mohamed Khalfella
> <mkhalfella@purestorage.com> wrote:
> >
> > Consider a write X that is issued to an LBA and times out without ever
> > being acknowledged. The initiator retries it on another path, where it
> > lands. A write Y to the same LBA follows and lands as well. The original
> > X is still in flight somewhere in the fabric, and when it finally
> > reaches the device it overwrites Y. A read now returns X, a write the
> > initiator gave up on long ago.
> >
> > Add a program to catch this. It opens the device O_DIRECT and, on each
> > iteration, issues a series of writes of distinct byte patterns to the
> > same LBA, the 4k block at offset 0, waits, then reads that block back
> > and checks every byte holds the pattern written last. Because the
> > patterns differ, the value that comes back identifies which write
> > reappeared.
> >
> > Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
> > ---
> >  src/.gitignore                  |  1 +
> >  src/Makefile                    |  1 +
> >  src/nvme-ghost-write-detector.c | 86 +++++++++++++++++++++++++++++++++
> >  3 files changed, 88 insertions(+)
> >  create mode 100644 src/nvme-ghost-write-detector.c
> >
> > diff --git a/src/.gitignore b/src/.gitignore
> > index e9869e1..9673be8 100644
> > --- a/src/.gitignore
> > +++ b/src/.gitignore
> > @@ -15,6 +15,7 @@
> >  /zbdioctl
> >  /miniublk
> >  /nvme-passthrough-meta
> > +/nvme-ghost-write-detector
> >  /ioctl-lbmd-query
> >  /nvme-passthru-admin-uring
> >  /nvme-delay-ioctl
> > diff --git a/src/Makefile b/src/Makefile
> > index dd64694..92b4d0c 100644
> > --- a/src/Makefile
> > +++ b/src/Makefile
> > @@ -24,6 +24,7 @@ C_TARGETS := \
> >         mount_clear_sock \
> >         nvme-delay-ioctl \
> >         nvme-passthrough-meta \
> > +       nvme-ghost-write-detector \
> >         ioctl-lbmd-query \
> >         nbdsetsize \
> >         openclose \
> > diff --git a/src/nvme-ghost-write-detector.c b/src/nvme-ghost-write-detector.c
> > new file mode 100644
> > index 0000000..bd42dde
> > --- /dev/null
> > +++ b/src/nvme-ghost-write-detector.c
> > @@ -0,0 +1,86 @@
> > +// SPDX-License-Identifier: GPL-3.0+
> > +// Copyright (C) 2026 Mohamed Khalfella
> > +
> > +#define _GNU_SOURCE
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <fcntl.h>
> > +#include <unistd.h>
> > +#include <string.h>
> > +#include <malloc.h>
> > +#include <errno.h>
> > +#include <libgen.h>
> 
> We don't need to include malloc.h

Okay, will drop it.

> > +
> > +#define BUF_SIZE       4096
> > +#define ITERATIONS     10
> > +#define DELAY          3               /* seconds delay between iterations */
> > +#define WRITE_COUNT    10
> > +
> > +#define WRITE_OFFSET   0
> > +#define READ_OFFSET    WRITE_OFFSET
> > +
> > +int main(int argc, char **argv)
> > +{
> > +       int fd, i, w, off, ret;
> > +       char *buff;
> > +
> 
> This is a bit pedantic but:
> 
> if (argc < 1)
>   return 1;

See below "if (argc < 2)". We need at least one argument the nvme device
to run IOs on. arg[0] is the program name, and arg[1] is the device name.

> 
> > +       fprintf(stdout, "starting %s test program\n", basename(argv[0]));
> > +
> > +       if (argc < 2) {
> > +               fprintf(stderr, "usage: %s /dev/nvmeXnY", argv[0]);
> > +               return 1;
> > +       }
> > +
> > +       fd = open(argv[1], O_RDWR | O_DIRECT);
> > +       if (fd < 0) {
> > +               fprintf(stderr, "failed to open device, errno = %d\n", errno);
> > +               return 1;
> > +       }
> > +
> > +       ret = posix_memalign((void **)&buff, BUF_SIZE, BUF_SIZE);
> > +       if (ret) {
> > +               fprintf(stderr, "failed to allocate buffer, ret = %d\n", ret);
> > +               goto out;
> > +       }
> > +
> > +       for (i = 0; i < ITERATIONS; i++) {
> > +               fprintf(stdout, "iteration number %d, writing data\n", i);
> > +
> > +               for (w = 0; w < WRITE_COUNT; w++) {
> > +                       memset(buff, w, BUF_SIZE);
> > +                       ret = pwrite(fd, buff, BUF_SIZE, WRITE_OFFSET);
> > +                       if (ret != BUF_SIZE) {
> > +                               fprintf(stderr, "failed to write buff, "
> > +                                               "ret = %d, errno = %d\n",
> > +                                               ret, errno);
> > +                               goto out;
> > +                       }
> > +               }
> > +
> > +               sleep(5);
> 
> There should be a macro for this.

Okay, will do that in next revision.

> 
> Thanks,
> Jesse Taube
> 
> > +               fprintf(stdout, "validating written data\n");
> > +
> > +               ret = pread(fd, buff, BUF_SIZE, READ_OFFSET);
> > +               if (ret != BUF_SIZE) {
> > +                       fprintf(stderr, "failed to read buff, "
> > +                                       "ret = %d, errno = %d\n",
> > +                                       ret, errno);
> > +                       goto out;
> > +               }
> > +
> > +               for (off = 0; off < BUF_SIZE; off++) {
> > +                       if (buff[off] != WRITE_COUNT - 1) {
> > +                               fprintf(stdout, "validation failed\n");
> > +                               goto out;
> > +                       }
> > +               }
> > +
> > +               fprintf(stdout, "successfully validated\n");
> > +               sleep(DELAY);
> > +       }
> > +
> > +out:
> > +       fprintf(stdout, "finished %s test program\n", basename(argv[0]));
> > +       close(fd);
> > +       return ret;
> > +}
> > --
> > 2.55.0
> >
> 

  reply	other threads:[~2026-09-23 17:00 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 [this message]
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

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=20260923170023.GG2931-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