Compare commits

..

No commits in common. "c9-beta" and "c8" have entirely different histories.
c9-beta ... c8

12 changed files with 580 additions and 1872 deletions

View File

@ -1,2 +1 @@
cef1ecfa810d379c0276aaff5031e63cde331938 SOURCES/fio-3.35.tar.bz2
4d27be918b3639125f311a1179092fea9c8c4c93 SOURCES/pmemblk.png
cad3b3d78c5c2c9a116ee53642eec17a77c5ead2 SOURCES/fio-3.19.tar.bz2

3
.gitignore vendored
View File

@ -1,2 +1 @@
SOURCES/fio-3.35.tar.bz2
SOURCES/pmemblk.png
SOURCES/fio-3.19.tar.bz2

View File

@ -0,0 +1,187 @@
From e1bcd541f63f9029f6c50116831303ad06292edc Mon Sep 17 00:00:00 2001
From: Song Liu <songliubraving@fb.com>
Date: Sun, 17 May 2020 22:39:49 -0700
Subject: [PATCH] Add option latency_run to continue enable latency_target
Currently, latency_target run will exist once fio find the highest queue
depth that meets latency_target. Add option latency_run. If set, fio will
continue running and try to meet latency_target by adusting queue depth.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
HOWTO | 7 +++++++
cconv.c | 2 ++
fio.1 | 5 +++++
fio.h | 1 +
io_u.c | 18 +++++++++++++++++-
options.c | 10 ++++++++++
server.h | 2 +-
thread_options.h | 2 ++
8 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/HOWTO b/HOWTO
index 430c7b62..f0b4ffe4 100644
--- a/HOWTO
+++ b/HOWTO
@@ -2551,6 +2551,13 @@ I/O latency
defaults to 100.0, meaning that all I/Os must be equal or below to the value
set by :option:`latency_target`.
+.. option:: latency_run=bool
+
+ Used with :option:`latency_target`. If false (default), fio will find
+ the highest queue depth that meets :option:`latency_target` and exit. If
+ true, fio will continue running and try to meet :option:`latency_target`
+ by adjusting queue depth.
+
.. option:: max_latency=time
If set, fio will exit the job with an ETIMEDOUT error if it exceeds this
diff --git a/cconv.c b/cconv.c
index 48218dc4..449bcf7b 100644
--- a/cconv.c
+++ b/cconv.c
@@ -288,6 +288,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
o->latency_window = le64_to_cpu(top->latency_window);
o->max_latency = le64_to_cpu(top->max_latency);
o->latency_percentile.u.f = fio_uint64_to_double(le64_to_cpu(top->latency_percentile.u.i));
+ o->latency_run = le32_to_cpu(top->latency_run);
o->compress_percentage = le32_to_cpu(top->compress_percentage);
o->compress_chunk = le32_to_cpu(top->compress_chunk);
o->dedupe_percentage = le32_to_cpu(top->dedupe_percentage);
@@ -487,6 +488,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
top->latency_window = __cpu_to_le64(o->latency_window);
top->max_latency = __cpu_to_le64(o->max_latency);
top->latency_percentile.u.i = __cpu_to_le64(fio_double_to_uint64(o->latency_percentile.u.f));
+ top->latency_run = __cpu_to_le32(o->latency_run);
top->compress_percentage = cpu_to_le32(o->compress_percentage);
top->compress_chunk = cpu_to_le32(o->compress_chunk);
top->dedupe_percentage = cpu_to_le32(o->dedupe_percentage);
diff --git a/fio.1 b/fio.1
index a2379f98..3a7a359b 100644
--- a/fio.1
+++ b/fio.1
@@ -2275,6 +2275,11 @@ The percentage of I/Os that must fall within the criteria specified by
defaults to 100.0, meaning that all I/Os must be equal or below to the value
set by \fBlatency_target\fR.
.TP
+.BI latency_run \fR=\fPbool
+Used with \fBlatency_target\fR. If false (default), fio will find the highest
+queue depth that meets \fBlatency_target\fR and exit. If true, fio will continue
+running and try to meet \fBlatency_target\fR by adjusting queue depth.
+.TP
.BI max_latency \fR=\fPtime
If set, fio will exit the job with an ETIMEDOUT error if it exceeds this
maximum latency. When the unit is omitted, the value is interpreted in
diff --git a/fio.h b/fio.h
index bbf057c1..7610026d 100644
--- a/fio.h
+++ b/fio.h
@@ -377,6 +377,7 @@ struct thread_data {
unsigned int latency_qd_high;
unsigned int latency_qd_low;
unsigned int latency_failed;
+ unsigned int latency_stable_count;
uint64_t latency_ios;
int latency_end_run;
diff --git a/io_u.c b/io_u.c
index aa8808b8..ae1438fd 100644
--- a/io_u.c
+++ b/io_u.c
@@ -1391,6 +1391,7 @@ static bool __lat_target_failed(struct thread_data *td)
td->latency_qd_low--;
td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2;
+ td->latency_stable_count = 0;
dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
@@ -1440,6 +1441,21 @@ static void lat_target_success(struct thread_data *td)
td->latency_qd_low = td->latency_qd;
+ if (td->latency_qd + 1 == td->latency_qd_high) {
+ /*
+ * latency_qd will not incease on lat_target_success(), so
+ * called stable. If we stick with this queue depth, the
+ * final latency is likely lower than latency_target. Fix
+ * this by increasing latency_qd_high slowly. Use a naive
+ * heuristic here. If we get lat_target_success() 3 times
+ * in a row, increase latency_qd_high by 1.
+ */
+ if (++td->latency_stable_count >= 3) {
+ td->latency_qd_high++;
+ td->latency_stable_count = 0;
+ }
+ }
+
/*
* If we haven't failed yet, we double up to a failing value instead
* of bisecting from highest possible queue depth. If we have set
@@ -1459,7 +1475,7 @@ static void lat_target_success(struct thread_data *td)
* Same as last one, we are done. Let it run a latency cycle, so
* we get only the results from the targeted depth.
*/
- if (td->latency_qd == qd) {
+ if (!o->latency_run && td->latency_qd == qd) {
if (td->latency_end_run) {
dprint(FD_RATE, "We are done\n");
td->done = 1;
diff --git a/options.c b/options.c
index b18cea33..da401aed 100644
--- a/options.c
+++ b/options.c
@@ -3672,6 +3672,16 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_LATPROF,
},
+ {
+ .name = "latency_run",
+ .lname = "Latency Run",
+ .type = FIO_OPT_BOOL,
+ .off1 = offsetof(struct thread_options, latency_run),
+ .help = "Keep adjusting queue depth to match latency_target",
+ .def = "0",
+ .category = FIO_OPT_C_IO,
+ .group = FIO_OPT_G_LATPROF,
+ },
{
.name = "invalidate",
.lname = "Cache invalidate",
diff --git a/server.h b/server.h
index 279b6917..de01a5c8 100644
--- a/server.h
+++ b/server.h
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
};
enum {
- FIO_SERVER_VER = 82,
+ FIO_SERVER_VER = 83,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
diff --git a/thread_options.h b/thread_options.h
index c78ed43d..09ccd5b2 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -324,6 +324,7 @@ struct thread_options {
unsigned long long latency_target;
unsigned long long latency_window;
fio_fp64_t latency_percentile;
+ uint32_t latency_run;
unsigned int sig_figs;
@@ -612,6 +613,7 @@ struct thread_options_pack {
uint64_t latency_window;
uint64_t max_latency;
fio_fp64_t latency_percentile;
+ uint32_t latency_run;
uint32_t sig_figs;
--
2.17.0

View File

@ -1,722 +0,0 @@
From 2383a1ec2ad9090259f6d200b92676acff37de3b Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Fri, 9 Jun 2023 18:18:48 +0200
Subject: [PATCH] Revert "pmemblk: remove pmemblk engine"
This reverts commit 04c1cdc4c108c6537681ab7c50daaed6d2fb4c93.
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
HOWTO.rst | 5 +
Makefile | 5 +
ci/actions-install.sh | 1 +
configure | 41 ++++
engines/pmemblk.c | 449 ++++++++++++++++++++++++++++++++++++++++
examples/pmemblk.fio | 71 +++++++
fio.1 | 5 +
options.c | 6 +
os/windows/examples.wxs | 4 +
10 files changed, 587 insertions(+)
create mode 100644 engines/pmemblk.c
create mode 100644 examples/pmemblk.fio
diff --git a/HOWTO.rst b/HOWTO.rst
index 32fff5ecbde42cf894214f766f38130dba079760..4f003524f69e5cced1195fb0f7efcc2590648122 100644
--- a/HOWTO.rst
+++ b/HOWTO.rst
@@ -2147,6 +2147,11 @@ I/O engine
before overwriting. The `trimwrite` mode works well for this
constraint.
+ **pmemblk**
+ Read and write using filesystem DAX to a file on a filesystem
+ mounted with DAX on a persistent memory device through the PMDK
+ libpmemblk library.
+
**dev-dax**
Read and write using device DAX to a persistent memory device (e.g.,
/dev/dax0.0) through the PMDK libpmem library.
diff --git a/Makefile b/Makefile
index 6d7fd4e2bbbdeb196d22299d379bebb29172d538..89205ebf498f957ceedefdf1b0e565f08c85060f 100644
--- a/Makefile
+++ b/Makefile
@@ -208,6 +208,11 @@ ifdef CONFIG_MTD
SOURCE += oslib/libmtd.c
SOURCE += oslib/libmtd_legacy.c
endif
+ifdef CONFIG_PMEMBLK
+ pmemblk_SRCS = engines/pmemblk.c
+ pmemblk_LIBS = -lpmemblk
+ ENGINES += pmemblk
+endif
ifdef CONFIG_LINUX_DEVDAX
dev-dax_SRCS = engines/dev-dax.c
dev-dax_LIBS = -lpmem
diff --git a/ci/actions-install.sh b/ci/actions-install.sh
index 95241e78825a9939814a747daf486f866949e392..2f1a0cbaeef4b528a93813d18b94f9bc041bfa04 100755
--- a/ci/actions-install.sh
+++ b/ci/actions-install.sh
@@ -47,6 +47,7 @@ DPKGCFG
libnbd-dev
libpmem-dev
libpmem2-dev
+ libpmemblk-dev
libprotobuf-c-dev
librbd-dev
libtcmalloc-minimal4
diff --git a/configure b/configure
index 74416fd48bc73e35cd8fd5440b9733efd1d0adbb..f6b160c99d374034ba308b74a306e3eb1570be1e 100755
--- a/configure
+++ b/configure
@@ -163,6 +163,7 @@ show_help="no"
exit_val=0
gfio_check="no"
libhdfs="no"
+pmemblk="no"
devdax="no"
pmem="no"
cuda="no"
@@ -2260,6 +2261,43 @@ if test "$libpmem" = "yes" && test "$disable_pmem" = "no"; then
fi
fi
+##########################################
+# Check whether we have libpmemblk
+# libpmem is a prerequisite
+if test "$libpmemblk" != "yes" ; then
+ libpmemblk="no"
+fi
+if test "$libpmem" = "yes"; then
+ cat > $TMPC << EOF
+#include <libpmemblk.h>
+int main(int argc, char **argv)
+{
+ PMEMblkpool *pbp;
+ pbp = pmemblk_open("", 0);
+ return 0;
+}
+EOF
+ if compile_prog "" "-lpmemblk" "libpmemblk"; then
+ libpmemblk="yes"
+ fi
+fi
+print_config "libpmemblk" "$libpmemblk"
+
+# Choose libpmem-based ioengines
+if test "$libpmem" = "yes" && test "$disable_pmem" = "no"; then
+ devdax="yes"
+ if test "$libpmem1_5" = "yes"; then
+ pmem="yes"
+ fi
+ if test "$libpmemblk" = "yes"; then
+ pmemblk="yes"
+ fi
+fi
+
+##########################################
+# Report whether pmemblk engine is enabled
+print_config "PMDK pmemblk engine" "$pmemblk"
+
##########################################
# Report whether dev-dax engine is enabled
print_config "PMDK dev-dax engine" "$devdax"
@@ -3188,6 +3226,9 @@ fi
if test "$mtd" = "yes" ; then
output_sym "CONFIG_MTD"
fi
+if test "$pmemblk" = "yes" ; then
+ output_sym "CONFIG_PMEMBLK"
+fi
if test "$devdax" = "yes" ; then
output_sym "CONFIG_LINUX_DEVDAX"
fi
diff --git a/engines/pmemblk.c b/engines/pmemblk.c
new file mode 100644
index 0000000000000000000000000000000000000000..849d8a15a0da59d07209c2475b78a1e4098c143a
--- /dev/null
+++ b/engines/pmemblk.c
@@ -0,0 +1,449 @@
+/*
+ * pmemblk: IO engine that uses PMDK libpmemblk to read and write data
+ *
+ * Copyright (C) 2016 Hewlett Packard Enterprise Development LP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation..
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * pmemblk engine
+ *
+ * IO engine that uses libpmemblk to read and write data
+ *
+ * To use:
+ * ioengine=pmemblk
+ *
+ * Other relevant settings:
+ * thread=1 REQUIRED
+ * iodepth=1
+ * direct=1
+ * unlink=1
+ * filename=/mnt/pmem0/fiotestfile,BSIZE,FSIZEMiB
+ *
+ * thread must be set to 1 for pmemblk as multiple processes cannot
+ * open the same block pool file.
+ *
+ * iodepth should be set to 1 as pmemblk is always synchronous.
+ * Use numjobs to scale up.
+ *
+ * direct=1 is implied as pmemblk is always direct. A warning message
+ * is printed if this is not specified.
+ *
+ * unlink=1 removes the block pool file after testing, and is optional.
+ *
+ * The pmem device must have a DAX-capable filesystem and be mounted
+ * with DAX enabled. filename must point to a file on that filesystem.
+ *
+ * Example:
+ * mkfs.xfs /dev/pmem0
+ * mkdir /mnt/pmem0
+ * mount -o dax /dev/pmem0 /mnt/pmem0
+ *
+ * When specifying the filename, if the block pool file does not already
+ * exist, then the pmemblk engine creates the pool file if you specify
+ * the block and file sizes. BSIZE is the block size in bytes.
+ * FSIZEMB is the pool file size in MiB.
+ *
+ * See examples/pmemblk.fio for more.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <libpmem.h>
+#include <libpmemblk.h>
+
+#include "../fio.h"
+
+/*
+ * libpmemblk
+ */
+typedef struct fio_pmemblk_file *fio_pmemblk_file_t;
+
+struct fio_pmemblk_file {
+ fio_pmemblk_file_t pmb_next;
+ char *pmb_filename;
+ uint64_t pmb_refcnt;
+ PMEMblkpool *pmb_pool;
+ size_t pmb_bsize;
+ size_t pmb_nblocks;
+};
+
+static fio_pmemblk_file_t Cache;
+
+static pthread_mutex_t CacheLock = PTHREAD_MUTEX_INITIALIZER;
+
+#define PMB_CREATE (0x0001) /* should create file */
+
+fio_pmemblk_file_t fio_pmemblk_cache_lookup(const char *filename)
+{
+ fio_pmemblk_file_t i;
+
+ for (i = Cache; i != NULL; i = i->pmb_next)
+ if (!strcmp(filename, i->pmb_filename))
+ return i;
+
+ return NULL;
+}
+
+static void fio_pmemblk_cache_insert(fio_pmemblk_file_t pmb)
+{
+ pmb->pmb_next = Cache;
+ Cache = pmb;
+}
+
+static void fio_pmemblk_cache_remove(fio_pmemblk_file_t pmb)
+{
+ fio_pmemblk_file_t i;
+
+ if (pmb == Cache) {
+ Cache = Cache->pmb_next;
+ pmb->pmb_next = NULL;
+ return;
+ }
+
+ for (i = Cache; i != NULL; i = i->pmb_next)
+ if (pmb == i->pmb_next) {
+ i->pmb_next = i->pmb_next->pmb_next;
+ pmb->pmb_next = NULL;
+ return;
+ }
+}
+
+/*
+ * to control block size and gross file size at the libpmemblk
+ * level, we allow the block size and file size to be appended
+ * to the file name:
+ *
+ * path[,bsize,fsizemib]
+ *
+ * note that we do not use the fio option "filesize" to dictate
+ * the file size because we can only give libpmemblk the gross
+ * file size, which is different from the net or usable file
+ * size (which is probably what fio wants).
+ *
+ * the final path without the parameters is returned in ppath.
+ * the block size and file size are returned in pbsize and fsize.
+ *
+ * note that the user specifies the file size in MiB, but
+ * we return bytes from here.
+ */
+static void pmb_parse_path(const char *pathspec, char **ppath, uint64_t *pbsize,
+ uint64_t *pfsize)
+{
+ char *path;
+ char *s;
+ uint64_t bsize;
+ uint64_t fsizemib;
+
+ path = strdup(pathspec);
+ if (!path) {
+ *ppath = NULL;
+ return;
+ }
+
+ /* extract sizes, if given */
+ s = strrchr(path, ',');
+ if (s && (fsizemib = strtoull(s + 1, NULL, 10))) {
+ *s = 0;
+ s = strrchr(path, ',');
+ if (s && (bsize = strtoull(s + 1, NULL, 10))) {
+ *s = 0;
+ *ppath = path;
+ *pbsize = bsize;
+ *pfsize = fsizemib << 20;
+ return;
+ }
+ }
+
+ /* size specs not found */
+ strcpy(path, pathspec);
+ *ppath = path;
+ *pbsize = 0;
+ *pfsize = 0;
+}
+
+static fio_pmemblk_file_t pmb_open(const char *pathspec, int flags)
+{
+ fio_pmemblk_file_t pmb;
+ char *path = NULL;
+ uint64_t bsize = 0;
+ uint64_t fsize = 0;
+
+ pmb_parse_path(pathspec, &path, &bsize, &fsize);
+ if (!path)
+ return NULL;
+
+ pthread_mutex_lock(&CacheLock);
+
+ pmb = fio_pmemblk_cache_lookup(path);
+ if (!pmb) {
+ pmb = malloc(sizeof(*pmb));
+ if (!pmb)
+ goto error;
+
+ /* try opening existing first, create it if needed */
+ pmb->pmb_pool = pmemblk_open(path, bsize);
+ if (!pmb->pmb_pool && (errno == ENOENT) &&
+ (flags & PMB_CREATE) && (0 < fsize) && (0 < bsize)) {
+ pmb->pmb_pool =
+ pmemblk_create(path, bsize, fsize, 0644);
+ }
+ if (!pmb->pmb_pool) {
+ log_err("pmemblk: unable to open pmemblk pool file %s (%s)\n",
+ path, strerror(errno));
+ goto error;
+ }
+
+ pmb->pmb_filename = path;
+ pmb->pmb_next = NULL;
+ pmb->pmb_refcnt = 0;
+ pmb->pmb_bsize = pmemblk_bsize(pmb->pmb_pool);
+ pmb->pmb_nblocks = pmemblk_nblock(pmb->pmb_pool);
+
+ fio_pmemblk_cache_insert(pmb);
+ } else {
+ free(path);
+ }
+
+ pmb->pmb_refcnt += 1;
+
+ pthread_mutex_unlock(&CacheLock);
+
+ return pmb;
+
+error:
+ if (pmb) {
+ if (pmb->pmb_pool)
+ pmemblk_close(pmb->pmb_pool);
+ pmb->pmb_pool = NULL;
+ pmb->pmb_filename = NULL;
+ free(pmb);
+ }
+ if (path)
+ free(path);
+
+ pthread_mutex_unlock(&CacheLock);
+ return NULL;
+}
+
+static void pmb_close(fio_pmemblk_file_t pmb, const bool keep)
+{
+ pthread_mutex_lock(&CacheLock);
+
+ pmb->pmb_refcnt--;
+
+ if (!keep && !pmb->pmb_refcnt) {
+ pmemblk_close(pmb->pmb_pool);
+ pmb->pmb_pool = NULL;
+ free(pmb->pmb_filename);
+ pmb->pmb_filename = NULL;
+ fio_pmemblk_cache_remove(pmb);
+ free(pmb);
+ }
+
+ pthread_mutex_unlock(&CacheLock);
+}
+
+static int pmb_get_flags(struct thread_data *td, uint64_t *pflags)
+{
+ static int thread_warned = 0;
+ static int odirect_warned = 0;
+
+ uint64_t flags = 0;
+
+ if (!td->o.use_thread) {
+ if (!thread_warned) {
+ thread_warned = 1;
+ log_err("pmemblk: must set thread=1 for pmemblk engine\n");
+ }
+ return 1;
+ }
+
+ if (!td->o.odirect && !odirect_warned) {
+ odirect_warned = 1;
+ log_info("pmemblk: direct == 0, but pmemblk is always direct\n");
+ }
+
+ if (td->o.allow_create)
+ flags |= PMB_CREATE;
+
+ (*pflags) = flags;
+ return 0;
+}
+
+static int fio_pmemblk_open_file(struct thread_data *td, struct fio_file *f)
+{
+ uint64_t flags = 0;
+ fio_pmemblk_file_t pmb;
+
+ if (pmb_get_flags(td, &flags))
+ return 1;
+
+ pmb = pmb_open(f->file_name, flags);
+ if (!pmb)
+ return 1;
+
+ FILE_SET_ENG_DATA(f, pmb);
+ return 0;
+}
+
+static int fio_pmemblk_close_file(struct thread_data fio_unused *td,
+ struct fio_file *f)
+{
+ fio_pmemblk_file_t pmb = FILE_ENG_DATA(f);
+
+ if (pmb)
+ pmb_close(pmb, false);
+
+ FILE_SET_ENG_DATA(f, NULL);
+ return 0;
+}
+
+static int fio_pmemblk_get_file_size(struct thread_data *td, struct fio_file *f)
+{
+ uint64_t flags = 0;
+ fio_pmemblk_file_t pmb = FILE_ENG_DATA(f);
+
+ if (fio_file_size_known(f))
+ return 0;
+
+ if (!pmb) {
+ if (pmb_get_flags(td, &flags))
+ return 1;
+ pmb = pmb_open(f->file_name, flags);
+ if (!pmb)
+ return 1;
+ }
+
+ f->real_file_size = pmb->pmb_bsize * pmb->pmb_nblocks;
+
+ fio_file_set_size_known(f);
+
+ if (!FILE_ENG_DATA(f))
+ pmb_close(pmb, true);
+
+ return 0;
+}
+
+static enum fio_q_status fio_pmemblk_queue(struct thread_data *td,
+ struct io_u *io_u)
+{
+ struct fio_file *f = io_u->file;
+ fio_pmemblk_file_t pmb = FILE_ENG_DATA(f);
+
+ unsigned long long off;
+ unsigned long len;
+ void *buf;
+
+ fio_ro_check(td, io_u);
+
+ switch (io_u->ddir) {
+ case DDIR_READ:
+ case DDIR_WRITE:
+ off = io_u->offset;
+ len = io_u->xfer_buflen;
+
+ io_u->error = EINVAL;
+ if (off % pmb->pmb_bsize)
+ break;
+ if (len % pmb->pmb_bsize)
+ break;
+ if ((off + len) / pmb->pmb_bsize > pmb->pmb_nblocks)
+ break;
+
+ io_u->error = 0;
+ buf = io_u->xfer_buf;
+ off /= pmb->pmb_bsize;
+ len /= pmb->pmb_bsize;
+ while (0 < len) {
+ if (io_u->ddir == DDIR_READ) {
+ if (0 != pmemblk_read(pmb->pmb_pool, buf, off)) {
+ io_u->error = errno;
+ break;
+ }
+ } else if (0 != pmemblk_write(pmb->pmb_pool, buf, off)) {
+ io_u->error = errno;
+ break;
+ }
+ buf += pmb->pmb_bsize;
+ off++;
+ len--;
+ }
+ off *= pmb->pmb_bsize;
+ len *= pmb->pmb_bsize;
+ io_u->resid = io_u->xfer_buflen - (off - io_u->offset);
+ break;
+ case DDIR_SYNC:
+ case DDIR_DATASYNC:
+ case DDIR_SYNC_FILE_RANGE:
+ /* we're always sync'd */
+ io_u->error = 0;
+ break;
+ default:
+ io_u->error = EINVAL;
+ break;
+ }
+
+ return FIO_Q_COMPLETED;
+}
+
+static int fio_pmemblk_unlink_file(struct thread_data *td, struct fio_file *f)
+{
+ char *path = NULL;
+ uint64_t bsize = 0;
+ uint64_t fsize = 0;
+
+ /*
+ * we need our own unlink in case the user has specified
+ * the block and file sizes in the path name. we parse
+ * the file_name to determine the file name we actually used.
+ */
+
+ pmb_parse_path(f->file_name, &path, &bsize, &fsize);
+ if (!path)
+ return ENOENT;
+
+ unlink(path);
+ free(path);
+ return 0;
+}
+
+FIO_STATIC struct ioengine_ops ioengine = {
+ .name = "pmemblk",
+ .version = FIO_IOOPS_VERSION,
+ .queue = fio_pmemblk_queue,
+ .open_file = fio_pmemblk_open_file,
+ .close_file = fio_pmemblk_close_file,
+ .get_file_size = fio_pmemblk_get_file_size,
+ .unlink_file = fio_pmemblk_unlink_file,
+ .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_NOEXTEND | FIO_NODISKUTIL,
+};
+
+static void fio_init fio_pmemblk_register(void)
+{
+ register_ioengine(&ioengine);
+}
+
+static void fio_exit fio_pmemblk_unregister(void)
+{
+ unregister_ioengine(&ioengine);
+}
diff --git a/examples/pmemblk.fio b/examples/pmemblk.fio
new file mode 100644
index 0000000000000000000000000000000000000000..59bb2a8a5acbf0e03d16a988f6ae0b9eb84575d2
--- /dev/null
+++ b/examples/pmemblk.fio
@@ -0,0 +1,71 @@
+[global]
+bs=1m
+ioengine=pmemblk
+norandommap
+time_based
+runtime=30
+group_reporting
+disable_lat=1
+disable_slat=1
+disable_clat=1
+clat_percentiles=0
+cpus_allowed_policy=split
+
+# For the pmemblk engine:
+#
+# IOs always complete immediately
+# IOs are always direct
+# Must use threads
+#
+iodepth=1
+direct=1
+thread
+numjobs=16
+#
+# Unlink can be used to remove the files when done, but if you are
+# using serial runs with stonewall, and you want the files to be created
+# only once and unlinked only at the very end, then put the unlink=1
+# in the last group. This is the method demonstrated here.
+#
+# Note that if you have a read-only group and if the files will be
+# newly created, then all of the data will read back as zero and the
+# read will be optimized, yielding performance that is different from
+# that of reading non-zero blocks (or unoptimized zero blocks).
+#
+unlink=0
+#
+# The pmemblk engine does IO to files in a DAX-mounted filesystem.
+# The filesystem should be created on an NVDIMM (e.g /dev/pmem0)
+# and then mounted with the '-o dax' option. Note that the engine
+# accesses the underlying NVDIMM directly, bypassing the kernel block
+# layer, so the usual filesystem/disk performance monitoring tools such
+# as iostat will not provide useful data.
+#
+# Here we specify a test file on each of two NVDIMMs. The first
+# number after the file name is the block size in bytes (4096 bytes
+# in this example). The second number is the size of the file to
+# create in MiB (1 GiB in this example); note that the actual usable
+# space available to fio will be less than this as libpmemblk requires
+# some space for metadata.
+#
+# Currently, the minimum block size is 512 bytes and the minimum file
+# size is about 17 MiB (these are libpmemblk requirements).
+#
+# While both files in this example have the same block size and file
+# size, this is not required.
+#
+filename=/pmem0/fio-test,4096,1024
+#filename=/pmem1/fio-test,4096,1024
+
+[pmemblk-write]
+rw=randwrite
+stonewall
+
+[pmemblk-read]
+rw=randread
+stonewall
+#
+# We're done, so unlink the file:
+#
+unlink=1
+
diff --git a/fio.1 b/fio.1
index 80bf3371a3556406cbcb29323bb21f55e769b9f9..3dc7e062a063d54bcd79120a7d6dc1ffd934b80c 100644
--- a/fio.1
+++ b/fio.1
@@ -1960,6 +1960,11 @@ e.g., on NAND, writing sequentially to erase blocks and discarding
before overwriting. The \fBtrimwrite\fR mode works well for this
constraint.
.TP
+.B pmemblk
+Read and write using filesystem DAX to a file on a filesystem
+mounted with DAX on a persistent memory device through the PMDK
+libpmemblk library.
+.TP
.B dev\-dax
Read and write using device DAX to a persistent memory device (e.g.,
/dev/dax0.0) through the PMDK libpmem library.
diff --git a/options.c b/options.c
index 8193fb29fe2b1cdfab8e745b9522aeb507f5361e..6c58577d8dbfd0a8dfd2b77e11c9be57e4aaaf10 100644
--- a/options.c
+++ b/options.c
@@ -2125,6 +2125,12 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.help = "Hadoop Distributed Filesystem (HDFS) engine"
},
#endif
+#ifdef CONFIG_PMEMBLK
+ { .ival = "pmemblk",
+ .help = "PMDK libpmemblk based IO engine",
+ },
+
+#endif
#ifdef CONFIG_IME
{ .ival = "ime_psync",
.help = "DDN's IME synchronous IO engine",
diff --git a/os/windows/examples.wxs b/os/windows/examples.wxs
index d70c77133f5a9f24908fffde9ce5ad20dbad2562..9308ba8be829c62b88cb06470a068cc2aef3f7dc 100755
--- a/os/windows/examples.wxs
+++ b/os/windows/examples.wxs
@@ -125,6 +125,9 @@
<Component>
<File Source="..\..\examples\numa.fio" />
</Component>
+ <Component>
+ <File Source="..\..\examples\pmemblk.fio" />
+ </Component>
<Component>
<File Source="..\..\examples\poisson-rate-submission.fio" />
</Component>
@@ -209,6 +212,7 @@
<ComponentRef Id="netio_multicast.fio" />
<ComponentRef Id="null.fio" />
<ComponentRef Id="numa.fio" />
+ <ComponentRef Id="pmemblk.fio" />
<ComponentRef Id="poisson_rate_submission.fio" />
<ComponentRef Id="rados.fio"/>
<ComponentRef Id="rand_zones.fio" />
--
2.41.0

View File

@ -0,0 +1,37 @@
From 8644ef7c4c49aa6d6492b3b250a06b841496d7fd Mon Sep 17 00:00:00 2001
From: Bart Van Assche <bvanassche@acm.org>
Date: Sat, 27 Jun 2020 07:26:24 -0700
Subject: [PATCH] Unbreak the pmemblk engine
Reported-by: Yi Zhang <yi.zhang@redhat.com>
Tested-by: Yi Zhang <yi.zhang@redhat.com>
Fixes: e9c7be0e32e6 ("pmemblk: Fix a memory leak")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
engines/pmemblk.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/engines/pmemblk.c b/engines/pmemblk.c
index 730f4d7..e2eaa15 100644
--- a/engines/pmemblk.c
+++ b/engines/pmemblk.c
@@ -220,14 +220,14 @@ static fio_pmemblk_file_t pmb_open(const char *pathspec, int flags)
pmb->pmb_nblocks = pmemblk_nblock(pmb->pmb_pool);
fio_pmemblk_cache_insert(pmb);
+ } else {
+ free(path);
}
pmb->pmb_refcnt += 1;
pthread_mutex_unlock(&CacheLock);
- free(path);
-
return pmb;
error:
--
2.9.5

View File

@ -0,0 +1,28 @@
From 2e3fb343ec883674a4927f2da983759bf90a0671 Mon Sep 17 00:00:00 2001
From: Song Liu <songliubraving@fb.com>
Date: Sun, 17 May 2020 22:46:21 -0700
Subject: [PATCH] init: fix unit of latency_window
latency_window has unit of microseconds, and is compared against
usec_window. Therefore, there is no need to fix it up to nanoseconds.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
init.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/init.c b/init.c
index b5315334..0431f700 100644
--- a/init.c
+++ b/init.c
@@ -956,7 +956,6 @@ static int fixup_options(struct thread_data *td)
*/
o->max_latency *= 1000ULL;
o->latency_target *= 1000ULL;
- o->latency_window *= 1000ULL;
return ret;
}
--
2.17.0

View File

@ -0,0 +1,56 @@
From 3721c7fe276dbbc93e584359f87913e58f96626e Mon Sep 17 00:00:00 2001
From: Sitsofe Wheeler <sitsofe@yahoo.com>
Date: Mon, 6 Dec 2021 20:02:53 +0000
Subject: [PATCH] os: detect PMULL support before enabling accelerated crc32c
on ARM
Issue #1239 shows a crash on a FUJITSU/A64FX ARM platform at the
following line:
crc/crc32c-arm64.c:
64 t1 = (uint64_t)vmull_p64(crc1, k2);
On armv8 PMULL crypto instructions like vmull_p64 are defined as
optional (see
https://github.com/google/crc32c/pull/6#issuecomment-328713398 and
https://github.com/dotnet/runtime/issues/35143#issuecomment-617263508 ).
Avoid the crash by gating use of the hardware accelerated ARM crc32c
path behind runtime detection of PMULL.
Fixes: https://github.com/axboe/fio/issues/1239
Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Tested-by: Yi Zhang <yi.zhang@redhat.com>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
os/os-linux.h | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/os/os-linux.h b/os/os-linux.h
index 808f1d02..3001140c 100644
--- a/os/os-linux.h
+++ b/os/os-linux.h
@@ -20,6 +20,9 @@
#ifdef ARCH_HAVE_CRC_CRYPTO
#include <sys/auxv.h>
+#ifndef HWCAP_PMULL
+#define HWCAP_PMULL (1 << 4)
+#endif /* HWCAP_PMULL */
#ifndef HWCAP_CRC32
#define HWCAP_CRC32 (1 << 7)
#endif /* HWCAP_CRC32 */
@@ -405,7 +408,8 @@ static inline bool os_cpu_has(cpu_features feature)
#ifdef ARCH_HAVE_CRC_CRYPTO
case CPU_ARM64_CRC32C:
hwcap = getauxval(AT_HWCAP);
- have_feature = (hwcap & HWCAP_CRC32) != 0;
+ have_feature = (hwcap & (HWCAP_PMULL | HWCAP_CRC32)) ==
+ (HWCAP_PMULL | HWCAP_CRC32);
break;
#endif
default:
--
2.38.1

View File

@ -0,0 +1,178 @@
From fd56c235caa42870e6dc33d661514375ea95ffc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Wild?= <wild.andre.ae@gmail.com>
Date: Fri, 14 Aug 2020 15:52:09 +0200
Subject: [PATCH] thread_options: Use unsigned int type for exit_what and
stonewall
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: 64402a8 ("Expand choices for exitall")
Fixes: https://github.com/axboe/fio/issues/1065
Signed-off-by: André Wild <wild.andre.ae@gmail.com>
---
cconv.c | 8 ++++----
examples/exitwhat.fio | 8 ++++----
fio.1 | 29 +++++++++++++++++++++--------
server.h | 2 +-
thread_options.h | 9 ++++-----
5 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/cconv.c b/cconv.c
index 2469389b..4b0c3490 100644
--- a/cconv.c
+++ b/cconv.c
@@ -237,8 +237,8 @@ void convert_thread_options_to_cpu(struct thread_options *o,
o->loops = le32_to_cpu(top->loops);
o->mem_type = le32_to_cpu(top->mem_type);
o->mem_align = le32_to_cpu(top->mem_align);
- o->exit_what = le16_to_cpu(top->exit_what);
- o->stonewall = le16_to_cpu(top->stonewall);
+ o->exit_what = le32_to_cpu(top->exit_what);
+ o->stonewall = le32_to_cpu(top->stonewall);
o->new_group = le32_to_cpu(top->new_group);
o->numjobs = le32_to_cpu(top->numjobs);
o->cpus_allowed_policy = le32_to_cpu(top->cpus_allowed_policy);
@@ -437,8 +437,8 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
top->loops = cpu_to_le32(o->loops);
top->mem_type = cpu_to_le32(o->mem_type);
top->mem_align = cpu_to_le32(o->mem_align);
- top->exit_what = cpu_to_le16(o->exit_what);
- top->stonewall = cpu_to_le16(o->stonewall);
+ top->exit_what = cpu_to_le32(o->exit_what);
+ top->stonewall = cpu_to_le32(o->stonewall);
top->new_group = cpu_to_le32(o->new_group);
top->numjobs = cpu_to_le32(o->numjobs);
top->cpus_allowed_policy = cpu_to_le32(o->cpus_allowed_policy);
diff --git a/examples/exitwhat.fio b/examples/exitwhat.fio
index a1099f0f..c91d7375 100644
--- a/examples/exitwhat.fio
+++ b/examples/exitwhat.fio
@@ -1,7 +1,7 @@
# We want to run fast1 as long as slow1 is running, but also have a cumulative
# report of fast1 (group_reporting=1/new_group=1). exitall=1 would not cause
# fast1 to stop after slow1 is done. Setting exit_what=stonewall will cause
-# alls jobs up until the next stonewall=1 setting to be stopped, when job slow1
+# alls jobs up until the next stonewall setting to be stopped, when job slow1
# finishes.
# In this example skipping forward to slow2/fast2. slow2 has exit_what=all set,
# which means all jobs will be cancelled when slow2 finishes. In particular,
@@ -15,7 +15,7 @@ group_reporting=1
exitall=1
[slow1]
-rw=r
+rw=read
numjobs=1
ioengine=sync
new_group=1
@@ -32,8 +32,8 @@ iodepth=32
rate=300,300,300
[slow2]
-stonewall=1
-rw=w
+stonewall
+rw=write
numjobs=1
ioengine=sync
new_group=1
diff --git a/fio.1 b/fio.1
index cdd105d7..1c90e4a5 100644
--- a/fio.1
+++ b/fio.1
@@ -2569,7 +2569,8 @@ been exceeded before retrying operations.
Wait for preceding jobs in the job file to exit, before starting this
one. Can be used to insert serialization points in the job file. A stone
wall also implies starting a new reporting group, see
-\fBgroup_reporting\fR.
+\fBgroup_reporting\fR. Optionally you can use `stonewall=0` to disable or
+`stonewall=1` to enable it.
.TP
.BI exitall
By default, fio will continue running all other jobs when one job finishes.
@@ -2577,15 +2578,27 @@ Sometimes this is not the desired action. Setting \fBexitall\fR will instead
make fio terminate all jobs in the same group, as soon as one job of that
group finishes.
.TP
-.BI exit_what
+.BI exit_what \fR=\fPstr
By default, fio will continue running all other jobs when one job finishes.
-Sometimes this is not the desired action. Setting \fBexit_all\fR will instead
+Sometimes this is not the desired action. Setting \fBexitall\fR will instead
make fio terminate all jobs in the same group. The option \fBexit_what\fR
-allows to control which jobs get terminated when \fBexitall\fR is enabled. The
-default is \fBgroup\fR and does not change the behaviour of \fBexitall\fR. The
-setting \fBall\fR terminates all jobs. The setting \fBstonewall\fR terminates
-all currently running jobs across all groups and continues execution with the
-next stonewalled group.
+allows you to control which jobs get terminated when \fBexitall\fR is enabled.
+The default value is \fBgroup\fR.
+The allowed values are:
+.RS
+.RS
+.TP
+.B all
+terminates all jobs.
+.TP
+.B group
+is the default and does not change the behaviour of \fBexitall\fR.
+.TP
+.B stonewall
+terminates all currently running jobs across all groups and continues
+execution with the next stonewalled group.
+.RE
+.RE
.TP
.BI exec_prerun \fR=\fPstr
Before running this job, issue the command specified through
diff --git a/server.h b/server.h
index de01a5c8..efa70e7c 100644
--- a/server.h
+++ b/server.h
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
};
enum {
- FIO_SERVER_VER = 83,
+ FIO_SERVER_VER = 84,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
diff --git a/thread_options.h b/thread_options.h
index 3fe48ecc..14f1cbe9 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -202,8 +202,8 @@ struct thread_options {
unsigned long long max_latency;
- unsigned short exit_what;
- unsigned short stonewall;
+ unsigned int exit_what;
+ unsigned int stonewall;
unsigned int new_group;
unsigned int numjobs;
os_cpu_mask_t cpumask;
@@ -494,8 +494,8 @@ struct thread_options_pack {
uint32_t mem_type;
uint32_t mem_align;
- uint16_t exit_what;
- uint16_t stonewall;
+ uint32_t exit_what;
+ uint32_t stonewall;
uint32_t new_group;
uint32_t numjobs;
/*
@@ -546,7 +546,6 @@ struct thread_options_pack {
uint32_t lat_percentiles;
uint32_t slat_percentiles;
uint32_t percentile_precision;
- uint32_t pad3;
fio_fp64_t percentile_list[FIO_IO_U_LIST_MAX_LEN];
uint8_t read_iolog_file[FIO_TOP_STR_MAX];
--
2.17.0

View File

@ -1,837 +0,0 @@
pub rsa4096 2011-10-17 [SC]
C0FC392DCADE26D975FA5E4AF7D358FB2971E0A6
uid Jens Axboe <axboe@kernel.dk>
uid [jpeg image of size 5172]
sub rsa4096 2011-10-17 [E]
2C5DCF0DAFBC972930D1DE5F28C8BEF174494BD8
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
rC5CZ/+w5pgqksY34twgbNSnUahwh8sI8Ee41qEJRc4oCFC8Q4GhlJOhLXyntHqU
m+ejz7073xBRNfRYZJVPROCaSfo6p3zT69JCzqJxVcvC6TmARF91Io23pCxLvQVb
W6dm4zblrLAorELZnzo5JgXcG35L7uI0lekeSo7KHH4fCCMX+m776ms6aBwG4S6Z
zI/jHd7rGzB382t2lHEXRFkcws5uSaTnpKToN970YD/WpfDqESouJaqIDLAfk3ou
OxwuSIBKybB50oY4WXOtGnItMYod9rsTIbm1Kc0S7IyvVRuTSfZBgKetAOlK59r6
FKTMLiBS6rzmky2IVQknBfoRXX8HfeAxENsRPvatuuQpOfwmpES9n0gEOKfwe4I8
FVU8CmeDqix4ZXcWWZSRayo//HneMYFBgrK06nMDM/xLe/JfV8nGIRF9hkW57Ka+
2XlqWyOLGZg0nRjr1fP9exPzXnxlXts47gXINcBSVDusMWVbxSMY0MMkgXKwnEyo
W/SSWNAwfV3q0rX02dcJX25QH/0rv7anjX5L4nOr8D88jjlkZYYhORNuOn4RxqzR
x3Qh5FoMtKIxQN7N4j/R04fThQEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgAB
AQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwg
JC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwh
MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
MjL/wAARCACWAHADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQF
BgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKB
kaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW
V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKz
tLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QA
HwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQA
AQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcY
GRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX
2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDktbunu5mmkYlnOTXP
SHmte/OF5NYzmtJsqAzNQsMmpqibqaxNCBfkcr2bpU0IycUyRNw9+1SokkSxyujK
rnAJGM/SkzajKzsy9FHxVyGLkcUWyBkBFaVpYz3DhYIXkY9lXNc8mezThZXPd/hn
NDJ4KtY4iN0TMsgHrnP8iK7CvB/D2q3XhGdpJdStrcN/rLZj5rN6ZVen1yK19W+M
M8kLRabYqhIwZZj/ACUH+tVGdo2Z5VfBTnVbhqmZHxGk/tXxlcrZRtN5SrGxQZ5A
56VxFzAlnn7TPFG39wHc35DpUuo65qGoBlkuWEZOfLjGxfyFZX2R5Oi4B7moS6s9
OCnCCguhuWOlxX09tALqKFp+fMnfaigDJya0Lfwyt74lg0axuo7suwVpo1O1e7Hn
rgVgLCSkasdxQbRXt/wy8Nixgn1edMSzgRw5HRBjJ/E/ypxV2LFVnSjzf1c8KvZA
yABt34Vksav3G3y8hwT6YrPY812yZ8/FCVG33qeOtNf71ZmglbE+l3a6VaNcElLi
IzWrZ44JBX68VkAE9BXsMtrpF38J9Kt7i9htdQihMsPmZB3hmxjjnPT8qluwXa2P
L7W/e0gR4443kV8MJBuGO3H1z+YrSfV9RvI9kl1J5f8Azzj+RfyXGfxrKkSNmLhg
CQGeMfwnPNWob+yQ7TJgj2rOWh7GHqQkk5MnSJgMABRUoh9TmrFq0FypMUqNjrz0
qx5A7DNZOR6UYpq6ZQCAdFApyICctk1YaMA8kUBB1xSuHLY6Hwb4Tl8T6myBxFbQ
ANK+M9egHuea9/ghS3t44YxiONQqj0ArjPhjor6Z4fa7myJL0hwp7IM4P45J+mK7
YnAzW9NWVz5vHVnUquK2R8ezDrVJ+DV6bnNUX61ucyEB5pr/AHjSr1ob71SWaOkW
/nXA+YAj1Gce9bermJ4EBuGuEjUKCrHCH0x2FVvCsRuL0w4GwKXcnv6CvUdD+H1v
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
ttsW4Qm8dOTwfQtoXCD/o5kUSg5mvNyIumY=
=o7ud
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmRtByEQHGF4Ym9lQGtl
cm5lbC5kawAKCRD301j7KXHgptKjEADY9cUdOoZxPdBaW8t/vkjDf3lw/RMF4b8j
hwoUtBmeottRGZkAKqE6aa63ICiuRUg1SHi1VzYEXdCelpN6xPHUjtKY+eXlrWsI
zsTvvRGTIXEade874S/Tt8daC1D2u6f27TAG94Az5E+RdQef3GQ5OjTCgv2bIz/y
GjczVcgZyr2Rs8Vu1RrwLZBAsh36EVdyxO9JyOKUTfJrotdRL4uxQh++TLW0uYd8
PKNCnX0qMUsoF/h8PJ8ui545X2I4Fwo7AisjHZKtE9gTpN+qb2kVOpdtEMwrV7fN
HCVdwGIi69AtIED856ItMpjLG4qf78idBy2MNxkggmBl8oY3OymvG2l5xb99B3u2
RQIPnJm5qU1gdwqy891fEPOGuPv8pJ4R7+ppoRPSu4ZIEjPMcm/ILNfWL8sZVN2u
Nv/WyvqfJLkCJDHKtiMBICKTXiqm0K0823AN7deygVvbkuGIftwvvWHNuj1ox+d6
JPkts5wrdlZDRwxjA5itofpGFNonT8wu1BqtgJq69mGSz/dJzDw7eWIuLzUlJf3u
rkMKmeL5IcuF4keQIKISe+1ZNDOwsc8gqzw4NF9ji/IV41ClFXKBT42EWghJN2SZ
j6PVNB1II+ngU+f8il4BFBngU0kj+431JTazlCAKo7n17Srbk+AVwVG3Ujx6iphw
IIUHF6esfg==
=lkTe
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,52 @@
From 640150c1b2c3cdbdd8baa5f1f3e7214a5c9a6533 Mon Sep 17 00:00:00 2001
From: Vincent Fu <vincent.fu@wdc.com>
Date: Tue, 31 Mar 2020 07:26:16 -0400
Subject: [PATCH] stat: eliminate extra log samples
b2a432bfbb6d inadvertently added extra log samples.
$ ./fio-canonical/fio --name=test --time_based --runtime=10s --write_lat_log=fio-07-b2a432 --log_avg_msec=1000 --size=1G --rw=rw
test: (g=0): rw=rw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
fio-3.17-93-gb2a4
Starting 1 process
...
$ cat fio-07-b2a432_clat.1.log
1000, 5851, 0, 0, 0
1000, 2551, 1, 0, 0
1000, 5028, 1, 0, 0
2000, 4175, 0, 0, 0
2000, 3214, 1, 0, 0
2000, 60619, 0, 0, 0
...
There should only be two lines at each timestamp (one for reads, one for
writes), but the first two timestamps have three lines each.
The cause is an inadvertent change in stat.c:add_log_sample() of
__add_stat_to_log to _add_stat_to_log. Reverting to the two-underscore
version resolves this issue.
Fixes: https://github.com/axboe/fio/issues/947
Fixes: b2a432bfbb6d ("Per-command priority: Priority logging and libaio/io_uring cmdprio_percentage")
Signed-off-by: Vincent Fu <vincent.fu@wdc.com>
---
stat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/stat.c b/stat.c
index d8c01d14..efa811d2 100644
--- a/stat.c
+++ b/stat.c
@@ -2749,7 +2749,7 @@ static unsigned long add_log_sample(struct thread_data *td,
return diff;
}
- _add_stat_to_log(iolog, elapsed, td->o.log_max != 0, priority_bit);
+ __add_stat_to_log(iolog, ddir, elapsed, td->o.log_max != 0, priority_bit);
iolog->avg_last[ddir] = elapsed - (this_window - iolog->avg_msec);
return iolog->avg_msec;
--
2.17.1

View File

@ -1,62 +1,33 @@
Name: fio
Version: 3.35
Release: 1%{?dist}
Version: 3.19
Release: 4%{?dist}
Summary: Multithreaded IO generation tool
Group: Applications/System
License: GPLv2
URL: http://git.kernel.dk/?p=fio.git;a=summary
Source0: http://brick.kernel.dk/snaps/%{name}-%{version}.tar.bz2
Source1: https://brick.kernel.dk/snaps/%{name}-%{version}.tar.bz2.asc
Source2: https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/plain/keys/F7D358FB2971E0A6.asc
Source3: pmemblk.png
Source: http://brick.kernel.dk/snaps/%{name}-%{version}.tar.bz2
Patch0: 0001-Revert-pmemblk-remove-pmemblk-engine.patch
Patch0: fio-eliminate-extra-log-samples.patch
Patch1: 0001-Unbreak-the-pmemblk-engine.patch
Patch2: 0001-init-fix-unit-of-latency_window.patch
Patch3: 0001-Add-option-latency_run-to-continue-enable-latency_ta.patch
Patch4: 0001-thread_options-Use-unsigned-int-type-for-exit_what-a.patch
Patch5: 0001-os-detect-PMULL-support-before-enabling-accelerated-.patch
BuildRequires: gcc
BuildRequires: gnupg2
BuildRequires: libaio-devel
BuildRequires: zlib-devel
BuildRequires: python3-devel
BuildRequires: libnbd-devel
BuildRequires: libcurl-devel
BuildRequires: openssl-devel
%ifarch x86_64 ppc64le
BuildRequires: python3-devel
%ifarch x86_64
BuildRequires: libpmem-devel
BuildRequires: libpmemblk-devel
%endif
%ifnarch %{arm} %{ix86}
BuildRequires: librbd1-devel
%endif
%ifnarch %{arm}
BuildRequires: numactl-devel
BuildRequires: librdmacm-devel
%endif
BuildRequires: make
# Don't create automated dependencies for the fio engines.
# https://bugzilla.redhat.com/show_bug.cgi?id=1884954
%global __provides_exclude_from ^%{_libdir}/fio/
# Main fio package has soft dependencies on all the engine
# subpackages, but allows the engines to be uninstalled if not needed
# or if the dependencies are too onerous.
Recommends: %{name}-engine-libaio
Recommends: %{name}-engine-http
Recommends: %{name}-engine-nbd
%ifarch x86-64 ppc64le
Recommends: %{name}-engine-dev-dax
Recommends: %{name}-engine-pmemblk
Recommends: %{name}-engine-libpmem
%endif
%ifnarch %{arm} %{ix86}
Recommends: %{name}-engine-rados
Recommends: %{name}-engine-rbd
%endif
%ifnarch %{arm}
Recommends: %{name}-engine-rdma
%endif
%description
fio is an I/O tool that will spawn a number of threads or processes doing
@ -66,289 +37,66 @@ otherwise parameters given to them overriding that setting is given.
The typical use of fio is to write a job file matching the io load
one wants to simulate.
%package engine-libaio
Summary: Linux libaio engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-libaio
Linux libaio engine for %{name}.
%package engine-http
Summary: HTTP engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-http
HTTP engine for %{name}.
%package engine-nbd
Summary: Network Block Device engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-nbd
Network Block Device (NBD) engine for %{name}.
%ifarch x86_64 ppc64le
%package engine-dev-dax
Summary: PMDK dev-dax engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-dev-dax
dev-dax engine for %{name}.
Read and write using device DAX to a persistent memory device
(e.g., /dev/dax0.0) through the PMDK libpmem library.
%endif
%ifarch x86_64 ppc64le
%package engine-pmemblk
Summary: PMDK pmemblk engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-pmemblk
pmemblk engine for %{name}.
Read and write using filesystem DAX to a file on a filesystem mounted with
DAX on a persistent memory device through the PMDK libpmemblk library.
%endif
%ifarch x86_64 ppc64le
%package engine-libpmem
Summary: PMDK pmemblk engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-libpmem
libpmem engine for %{name}.
Read and write using mmap I/O to a file on a filesystem mounted with DAX
on a persistent memory device through the PMDK libpmem library.
%endif
%ifnarch %{arm} %{ix86}
%package engine-rados
Summary: Rados engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-rados
Rados engine for %{name}.
%package engine-rbd
Summary: Rados Block Device engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-rbd
Rados Block Device (RBD) engine for %{name}.
%endif
%ifnarch %{arm}
%package engine-rdma
Summary: RDMA engine for %{name}.
Requires: %{name}%{?_isa} = %{version}-%{release}
%description engine-rdma
RDMA engine for %{name}.
%endif
%prep
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%autosetup -p1
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
pathfix.py -i %{__python3} -pn \
doc/conf.py \
tools/fio_jsonplus_clat2csv \
tools/fiologparser.py \
tools/hist/*.py \
tools/plot/fio2gnuplot \
t/steadystate_tests.py
# Edit /usr/local/lib path in os/os-linux.h to match Fedora conventions.
sed -e 's,/usr/local/lib/,%{_libdir}/,g' -i os/os-linux.h
t/*.py
%build
./configure --disable-optimizations --enable-libnbd --dynamic-libengines
./configure --disable-optimizations
EXTFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" make V=1 %{?_smp_mflags}
%install
make install prefix=%{_prefix} mandir=%{_mandir} libdir=%{_libdir}/fio DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p"
mkdir -p %{buildroot}/%{_docdir}/%{name}/examples/
install -p -m 0644 %{SOURCE3} %{buildroot}/%{_docdir}/%{name}/examples
make install prefix=%{_prefix} mandir=%{_mandir} DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p"
%files
%doc README.rst REPORTING-BUGS HOWTO.rst examples
%doc README REPORTING-BUGS COPYING HOWTO examples
%doc MORAL-LICENSE GFIO-TODO SERVER-TODO STEADYSTATE-TODO
%license COPYING
%dir %{_datadir}/%{name}
%dir %{_libdir}/fio/
%{_bindir}/*
%{_mandir}/man1/*
%{_datadir}/%{name}/*
%ifarch x86_64 ppc64le
%files engine-dev-dax
%{_libdir}/fio/fio-dev-dax.so
%endif
%files engine-http
%{_libdir}/fio/fio-http.so
%files engine-libaio
%{_libdir}/fio/fio-libaio.so
%ifarch x86_64 ppc64le
%files engine-libpmem
%{_libdir}/fio/fio-libpmem.so
%endif
%files engine-nbd
%{_libdir}/fio/fio-nbd.so
%ifarch x86_64 ppc64le
%files engine-pmemblk
%{_libdir}/fio/fio-pmemblk.so
%endif
%ifnarch %{arm} %{ix86}
%files engine-rados
%{_libdir}/fio/fio-rados.so
%files engine-rbd
%{_libdir}/fio/fio-rbd.so
%endif
%ifnarch %{arm}
%files engine-rdma
%{_libdir}/fio/fio-rdma.so
%endif
%changelog
* Sat May 27 2023 Pavel Reichl <preichl@redhat.com> - 3.35-1
- Rebase to new upstream release
- Do NOT drop support for pmemblk https://github.com/axboe/fio/commit/04c1cdc
- Add signature check
- Related: rhbz#2188805
* Mon Oct 31 2022 Pavel Reichl <preichl@redhat.com> - 3.19-4
- crc32c_arm64(): fio killed by SIGILL
Fix rhbz#1954143
* Mon Oct 24 2022 Pavel Reichl <preichl@redhat.com> - 3.27-8
- Fix fio failure with --verify=crc32c on arm
Related: rhbz#1974189
* Thu Aug 20 2020 Eric Sandeen <sandeen@redhat.com> 3.19-3
- Fix regression in stonewall (#1869305)
* Tue Feb 08 2022 Eric Sandeen <sandeen@redhat.com> - 3.27.7
- Use LDFLAGS when linking dynamic engines
Related: rhbz#2044858
* Tue Jul 14 2020 Eric Sandeen <sandeen@redhat.com> 3.19-2
- Fix regression in pmemblk engine (#1846843)
* Tue Aug 10 2021 Eric Sandeen <sandeen@redhat.com> - 3.27.5
- Add gating CI yaml file
* Mon Apr 20 2020 Eric Sandeen <sandeen@redhat.com> 3.19-1
- Rebase to new upstream + bugfix
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.27-4
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Fri Jun 07 2019 Eric Sandeen <sandeen@redhat.com> 3.7-5
- Rebuild w/ tests in place (#1681954)
* Thu Aug 05 2021 Eric Sandeen <sandeen@redhat.com> - 3.27-3
- Fix crash on --enghelp option
- Fix FTBFS with new kernel headers (bz#1984823)
* Wed Aug 01 2018 Charalampos Stratakis <cstratak@redhat.com> - 3.7-3
- Fix python shebangs in a more portable way
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.27-2
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Thu May 27 2021 Eric Sandeen <sandeen@redhat.com> - 3.27-1
- New upstream version
* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 3.25-4
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Mon Feb 08 2021 Eric Sandeen <sandeen@redhat.com> 3.25-3
- Fix segfault with external IO engines and multiple threads
- Enable dev-dax, pmemblk, libpmem engines for ppc64le
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.25-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Fri Dec 04 2020 Eric Sandeen <sandeen@redhat.com> 3.25-1
- New upstream version
* Thu Nov 12 2020 Eric Sandeen <sandeen@redhat.com> 3.24-1
- New upstream version
- Fix dynamic engine loading (#bz1894616)
* Mon Oct 05 2020 Richard W.M. Jones <rjones@redhat.com> 3.23-5
- Disable automatic provides for fio engines (RHBZ#1884954).
- Apply patch to change SONAME of fio engines (see comment 8 of above bug).
* Thu Oct 01 2020 Richard W.M. Jones <rjones@redhat.com> 3.23-3
- Add soft dependencies from main package to all the subpackages.
* Thu Oct 01 2020 Richard W.M. Jones <rjones@redhat.com> 3.23-2
- Enable dynamically loaded engines support.
- Move license to %%license section.
* Tue Sep 08 2020 Eric Sandeen <sandeen@redhat.com> 3.23-1
- New upstream version
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.21-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jul 20 2020 Eric Sandeen <sandeen@redhat.com> 3.21-1
- New upstream version
* Wed Jun 03 2020 Eric Sandeen <sandeen@redhat.com> 3.20-1
- New upstream version
* Fri May 15 2020 Martin Bukatovic <mbukatov@redhat.com> 3.19-3
- Enable http engine. (#1836323)
* Thu Apr 16 2020 Eric Sandeen <sandeen@redhat.com> 3.19-2
- Bugfix update: stat: eliminate extra log samples
* Thu Mar 12 2020 Eric Sandeen <sandeen@redhat.com> 3.19-1
- New upstream version
* Thu Feb 13 2020 Eric Sandeen <sandeen@redhat.com> 3.18-1
- New upstream version
- Fix gcc10 build
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.17-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Mon Dec 16 2019 Eric Sandeen <sandeen@redhat.com> 3.17-1
- New upstream version
* Wed Nov 06 2019 Richard W.M. Jones <rjones@redhat.com> 3.16-2
- Enable Network Block Device (libnbd) engine.
* Sat Sep 21 2019 Eric Sandeen <sandeen@redhat.com> 3.16-1
- New upstream version
* Fri Aug 16 2019 Eric Sandeen <sandeen@redhat.com> 3.15-1
- New upstream version
* Thu Aug 08 2019 Eric Sandeen <sandeen@redhat.com> 3.14-3
- Make all scripts explicitly call python3 (#1738819)
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.14-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Wed May 22 2019 Eric Sandeen <sandeen@redhat.com> 3.14-1
- New upstream version
* Thu Feb 14 2019 Eric Sandeen <sandeen@redhat.com> 3.13-1
- New upstream version
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.12-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Thu Jan 17 2019 Eric Sandeen <sandeen@redhat.com> 3.12-1
- New upstream version
* Wed Aug 22 2018 Eric Sandeen <sandeen@redhat.com> 3.8-1
- New upstream version
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.7-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Mon Jun 25 2018 Eric Sandeen <sandeen@redhat.com> 3.7-2
- Re-add python3 shebang patch (#1561477)
* Fri Jun 01 2018 Eric Sandeen <sandeen@redhat.com> 3.7-1
- New upstream version
* Fri Jun 01 2018 Eric Sandeen <sandeen@redhat.com> 3.6-3
- Complete the conversion to python3
* Wed May 16 2018 Eric Sandeen <sandeen@redhat.com> 3.6-2
- Make all python scripts python3 compliant and explicit
- Make all python scripts python3 compliant and explicit (#1561477)
* Wed Apr 18 2018 Eric Sandeen <sandeen@redhat.com> 3.6-1
- New upstream version