Re: [PATCH v2 1/2] page_fault: add mmap-backed ioengine for anonymous faults

Nico Pache <[email protected]> Thu, 12 Mar 2026 11:37:18 -0600
Newsgroups org.kernel.vger.fio
Message-ID <CAA1CXcAfV=FuY8hqDDnzfBLqSDqOAoBWCrvy+hByrcaK6zAAYA@mail.gmail.com>
On Thu, Mar 12, 2026 at 7:34=E2=80=AFAM Vincent Fu <[email protected]> wr=
ote:
>
> On Wed, Mar 11, 2026 at 11:52=E2=80=AFAM Nico Pache <[email protected]> w=
rote:
> >
> > Introduce a new ioengine that mmaps anonymous memory and copies data
> > on read/write to trigger page faults. This allows us to leverage FIOs
> > powerful framework for MM related testing, and will ideally allow us to
> > quickly expand testing, by leveraging previously FS related fio scripts=
.
> >
> > Signed-off-by: Nico Pache <[email protected]>
> > ---
> >  Makefile                |   2 +-
> >  engines/page_fault.c    | 116 ++++++++++++++++++++++++++++++++++++++++
> >  examples/page_fault.fio |  60 +++++++++++++++++++++
> >  3 files changed, 177 insertions(+), 1 deletion(-)
> >  create mode 100644 engines/page_fault.c
> >  create mode 100644 examples/page_fault.fio
> >
> > diff --git a/Makefile b/Makefile
> > index 0337e8fe..099e2f94 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -57,7 +57,7 @@ SOURCE :=3D     $(sort $(patsubst $(SRCDIR)/%,%,$(wil=
dcard $(SRCDIR)/crc/*.c)) \
> >                 smalloc.c filehash.c profile.c debug.c engines/cpu.c \
> >                 engines/mmap.c engines/sync.c engines/null.c engines/ne=
t.c \
> >                 engines/ftruncate.c engines/fileoperations.c \
> > -               engines/exec.c \
> > +               engines/exec.c engines/page_fault.c \
> >                 server.c client.c iolog.c backend.c libfio.c flow.c cco=
nv.c \
> >                 gettime-thread.c helpers.c json.c idletime.c td_error.c=
 \
> >                 profiles/tiobench.c profiles/act.c io_u_queue.c fileloc=
k.c \
> > diff --git a/engines/page_fault.c b/engines/page_fault.c
> > new file mode 100644
> > index 00000000..88108644
> > --- /dev/null
> > +++ b/engines/page_fault.c
> > @@ -0,0 +1,116 @@
> > +/*
> > + * page_fault engine
> > + *
> > + * IO engine that reads/writes directly to/from anonymous memory
> > + * by triggering page faults.
> > + */
> > +#include "fio.h"
> > +#include "ioengines.h"
> > +#include <sys/mman.h>
> > +
> > +struct fio_page_fault_data {
> > +  void *mmap_ptr;
> > +  size_t mmap_sz;
> > +};
> > +
> > +static int fio_page_fault_init(struct thread_data *td) {
>
> The style we follow is to put the { on a new line. Also please use
> tabs. We basically follow the kernel's style conventions. Did you use
> the default LLVM conventions with clang-format?

Hmm perhaps I called clang-format incorrectly. I assumed it would read
the format file automatically but that is not the case. Sorry, first
time using the clang-format function.

>
> > +  size_t total_io_size;
> > +  struct fio_page_fault_data *fpd;
> > +
> > +  if (td->o.nr_files > 1) {
> > +    log_err("page_fault engine does not support multiple files\n");
>
> How about, "fio: page_fault ioengine ..."?

Sounds good, yeah I wasnt thinking about the reporting format you guys
use. Ill keep that in mind.

>
> > +    return 1;
> > +  }
>
> Consider checking that td->o.offset =3D=3D 0 and emitting an error messag=
e
> saying that the offset option must be zero for this ioengine to work.

Hmm, I didnt even notice, but while doing my cleanup and ripping out
the other features I added I accidently removed the offset...

Ill add that back. Thanks :)

>
> > +
> > +  fpd =3D calloc(1, sizeof(*fpd));
> > +  if (!fpd)
> > +    return 1;
> > +
> > +  total_io_size =3D td->o.size;
> > +  fpd->mmap_sz =3D total_io_size;
> > +  fpd->mmap_ptr =3D mmap(NULL, total_io_size, PROT_READ | PROT_WRITE,
> > +                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> > +  if (fpd->mmap_ptr =3D=3D MAP_FAILED) {
> > +    free(fpd);
> > +    return 1;
> > +  }
> > +
> > +  td->io_ops_data =3D fpd;
> > +  FILE_SET_ENG_DATA(td->files[0], fpd);
>
> I would avoid directly manipulating files[] here. Since there is only
> a single instance of fpd, why not omit this and just access fpd via
> td->io_ops_data in queue()?

Yeah I had to switch to using io_ops_data directly and use the cleanup
hook (rather than close_file) because of a bug I found, but now it
just looks messy. Ill clean it up as you suggested! thanks.

Cheers,
-- Nico

>
> Vincent
>