ifeq ($(CONFIG_TARGET_OS), Linux)
SOURCE += diskutil.c fifo.c blktrace.c cgroup.c trim.c engines/sg.c \
- engines/binject.c oslib/linux-dev-lookup.c
+ oslib/linux-dev-lookup.c
LIBS += -lpthread -ldl
LDFLAGS += -rdynamic
endif
#define ARCH_HAVE_FFZ
-#ifdef ARCH_HAVE_CRC_CRYPTO
-#define ARCH_HAVE_ARM64_CRC_CRYPTO
-#endif
-
#endif
break;
} else if (io_u->ddir == DDIR_WRITE) {
io_u->ddir = DDIR_READ;
+ populate_verify_io_u(td, io_u);
break;
} else {
put_io_u(td, io_u);
break;
}
+ if (io_u->ddir == DDIR_WRITE && td->flags & TD_F_DO_VERIFY)
+ populate_verify_io_u(td, io_u);
+
ddir = io_u->ddir;
/*
static int switch_ioscheduler(struct thread_data *td)
{
#ifdef FIO_HAVE_IOSCHED_SWITCH
- char tmp[256], tmp2[128];
+ char tmp[256], tmp2[128], *p;
FILE *f;
int ret;
/*
* Read back and check that the selected scheduler is now the default.
*/
- memset(tmp, 0, sizeof(tmp));
- ret = fread(tmp, sizeof(tmp), 1, f);
+ ret = fread(tmp, 1, sizeof(tmp) - 1, f);
if (ferror(f) || ret < 0) {
td_verror(td, errno, "fread");
fclose(f);
return 1;
}
+ tmp[ret] = '\0';
/*
- * either a list of io schedulers or "none\n" is expected.
+ * either a list of io schedulers or "none\n" is expected. Strip the
+ * trailing newline.
*/
- tmp[strlen(tmp) - 1] = '\0';
+ p = tmp;
+ strsep(&p, "\n");
/*
* Write to "none" entry doesn't fail, so check the result here.
sprintf(log_pathname, "%s.%s", pdu->name, client->hostname);
if (store_direct) {
- ssize_t ret;
+ ssize_t wrote;
size_t sz;
int fd;
}
sz = cmd->pdu_len - sizeof(*pdu);
- ret = write(fd, pdu->samples, sz);
+ wrote = write(fd, pdu->samples, sz);
close(fd);
- if (ret != sz) {
+ if (wrote != sz) {
log_err("fio: short write on compressed log\n");
ret = 1;
goto out;
EOF
if compile_prog "" "" "posixaio" ; then
posix_aio="yes"
-elif compile_prog "" "-lrt" "posixaio"; then
+elif compile_prog "" "-lrt" "posixaio -lrt"; then
posix_aio="yes"
posix_aio_lrt="yes"
LIBS="-lrt $LIBS"
fi
if test "$cpu" = "arm64" ; then
cat > $TMPC <<EOF
-#include <sys/auxv.h>
#include <arm_acle.h>
#include <arm_neon.h>
+#include <sys/auxv.h>
int main(void)
{
- return 0;
+ /* Can we also do a runtime probe? */
+#if __linux__
+ return getauxval(AT_HWCAP);
+#else
+# error "Don't know how to do runtime probe for ARM CRC32c"
+#endif
}
EOF
- if compile_prog "-march=armv8-a+crc+crypto" "" ""; then
+ if compile_prog "-march=armv8-a+crc+crypto" "" "ARM CRC32c"; then
march_armv8_a_crc_crypto="yes"
- CFLAGS="$CFLAGS -march=armv8-a+crc+crypto -DARCH_HAVE_CRC_CRYPTO"
+ CFLAGS="$CFLAGS -march=armv8-a+crc+crypto"
march_set="yes"
fi
fi
echo "Note that some distros have separate packages for static libraries."
fi
fi
+if test "$march_armv8_a_crc_crypto" = "yes" ; then
+ output_sym "ARCH_HAVE_CRC_CRYPTO"
+fi
if test "$cuda" = "yes" ; then
output_sym "CONFIG_CUDA"
fi
#include "crc32c.h"
+#include "../os/os.h"
+
+bool crc32c_arm64_available = false;
+
+#ifdef ARCH_HAVE_CRC_CRYPTO
#define CRC32C3X8(ITR) \
crc1 = __crc32cd(crc1, *((const uint64_t *)data + 42*1 + (ITR)));\
CRC32C3X8((ITR)*7+6) \
} while(0)
-#ifndef HWCAP_CRC32
-#define HWCAP_CRC32 (1 << 7)
-#endif /* HWCAP_CRC32 */
-
-bool crc32c_arm64_available = false;
-
-#ifdef ARCH_HAVE_ARM64_CRC_CRYPTO
-
-#include <sys/auxv.h>
#include <arm_acle.h>
#include <arm_neon.h>
void crc32c_arm64_probe(void)
{
- unsigned long hwcap;
-
if (!crc32c_probed) {
- hwcap = getauxval(AT_HWCAP);
- crc32c_arm64_available = (hwcap & HWCAP_CRC32) != 0;
+ crc32c_arm64_available = os_cpu_has(CPU_ARM64_CRC32C);
crc32c_probed = true;
}
}
-#endif /* ARCH_HAVE_ARM64_CRC_CRYPTO */
+#endif /* ARCH_HAVE_CRC_CRYPTO */
}
}
-#endif /* ARCH_HAVE_SSE */
+#endif /* ARCH_HAVE_SSE4_2 */
extern bool crc32c_arm64_available;
extern bool crc32c_intel_available;
-#ifdef ARCH_HAVE_ARM64_CRC_CRYPTO
+#ifdef ARCH_HAVE_CRC_CRYPTO
extern uint32_t crc32c_arm64(unsigned char const *, unsigned long);
extern void crc32c_arm64_probe(void);
#else
static inline void crc32c_arm64_probe(void)
{
}
-#endif
+#endif /* ARCH_HAVE_CRC_CRYPTO */
#ifdef ARCH_HAVE_SSE4_2
extern uint32_t crc32c_intel(unsigned char const *, unsigned long);
static inline void crc32c_intel_probe(void)
{
}
-#endif
+#endif /* ARCH_HAVE_SSE4_2 */
static inline uint32_t fio_crc32c(unsigned char const *buf, unsigned long len)
{
+++ /dev/null
-/*
- * binject engine
- *
- * IO engine that uses the Linux binject interface to directly inject
- * bio's to block devices.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "../fio.h"
-
-#ifdef FIO_HAVE_BINJECT
-
-struct binject_data {
- struct b_user_cmd *cmds;
- struct io_u **events;
- struct pollfd *pfds;
- int *fd_flags;
-};
-
-struct binject_file {
- unsigned int bs;
- int minor;
- int fd;
-};
-
-static void binject_buc_init(struct binject_data *bd, struct io_u *io_u)
-{
- struct b_user_cmd *buc = &io_u->buc;
-
- memset(buc, 0, sizeof(*buc));
- binject_buc_set_magic(buc);
-
- buc->buf = (unsigned long) io_u->xfer_buf;
- buc->len = io_u->xfer_buflen;
- buc->offset = io_u->offset;
- buc->usr_ptr = (unsigned long) io_u;
-
- buc->flags = B_FLAG_NOIDLE | B_FLAG_UNPLUG;
- assert(buc->buf);
-}
-
-static int pollin_events(struct pollfd *pfds, int fds)
-{
- int i;
-
- for (i = 0; i < fds; i++)
- if (pfds[i].revents & POLLIN)
- return 1;
-
- return 0;
-}
-
-static unsigned int binject_read_commands(struct thread_data *td, void *buf,
- int left, int *err)
-{
- struct fio_file *f;
- int i, ret, events;
- char *p = buf;
-
-one_more:
- events = 0;
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- ret = read(bf->fd, p, left * sizeof(struct b_user_cmd));
- if (ret < 0) {
- if (errno == EAGAIN)
- continue;
- *err = -errno;
- td_verror(td, errno, "read");
- break;
- } else if (ret) {
- p += ret;
- events += ret / sizeof(struct b_user_cmd);
- }
- }
-
- if (*err || events)
- return events;
-
- usleep(1000);
- goto one_more;
-}
-
-static int fio_binject_getevents(struct thread_data *td, unsigned int min,
- unsigned int max,
- const struct timespec fio_unused *t)
-{
- struct binject_data *bd = td->io_ops_data;
- int left = max, ret, r = 0, ev_index = 0;
- void *buf = bd->cmds;
- unsigned int i, events;
- struct fio_file *f;
-
- /*
- * Fill in the file descriptors
- */
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- /*
- * don't block for min events == 0
- */
- if (!min)
- bd->fd_flags[i] = fio_set_fd_nonblocking(bf->fd, "binject");
- else
- bd->fd_flags[i] = -1;
-
- bd->pfds[i].fd = bf->fd;
- bd->pfds[i].events = POLLIN;
- }
-
- while (left) {
- while (!min) {
- ret = poll(bd->pfds, td->o.nr_files, -1);
- if (ret < 0) {
- if (!r)
- r = -errno;
- td_verror(td, errno, "poll");
- break;
- } else if (!ret)
- continue;
-
- if (pollin_events(bd->pfds, td->o.nr_files))
- break;
- }
-
- if (r < 0)
- break;
-
- events = binject_read_commands(td, buf, left, &r);
-
- if (r < 0)
- break;
-
- left -= events;
- r += events;
-
- for (i = 0; i < events; i++) {
- struct b_user_cmd *buc = (struct b_user_cmd *) buf + i;
-
- bd->events[ev_index] = (struct io_u *) (unsigned long) buc->usr_ptr;
- ev_index++;
- }
- }
-
- if (!min) {
- for_each_file(td, f, i) {
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- if (bd->fd_flags[i] == -1)
- continue;
-
- if (fcntl(bf->fd, F_SETFL, bd->fd_flags[i]) < 0)
- log_err("fio: binject failed to restore fcntl flags: %s\n", strerror(errno));
- }
- }
-
- if (r > 0)
- assert(ev_index == r);
-
- return r;
-}
-
-static int fio_binject_doio(struct thread_data *td, struct io_u *io_u)
-{
- struct b_user_cmd *buc = &io_u->buc;
- struct binject_file *bf = FILE_ENG_DATA(io_u->file);
- int ret;
-
- ret = write(bf->fd, buc, sizeof(*buc));
- if (ret < 0)
- return ret;
-
- return FIO_Q_QUEUED;
-}
-
-static int fio_binject_prep(struct thread_data *td, struct io_u *io_u)
-{
- struct binject_data *bd = td->io_ops_data;
- struct b_user_cmd *buc = &io_u->buc;
- struct binject_file *bf = FILE_ENG_DATA(io_u->file);
-
- if (io_u->xfer_buflen & (bf->bs - 1)) {
- log_err("read/write not sector aligned\n");
- return EINVAL;
- }
-
- if (io_u->ddir == DDIR_READ) {
- binject_buc_init(bd, io_u);
- buc->type = B_TYPE_READ;
- } else if (io_u->ddir == DDIR_WRITE) {
- binject_buc_init(bd, io_u);
- if (io_u->flags & IO_U_F_BARRIER)
- buc->type = B_TYPE_WRITEBARRIER;
- else
- buc->type = B_TYPE_WRITE;
- } else if (io_u->ddir == DDIR_TRIM) {
- binject_buc_init(bd, io_u);
- buc->type = B_TYPE_DISCARD;
- } else {
- assert(0);
- }
-
- return 0;
-}
-
-static int fio_binject_queue(struct thread_data *td, struct io_u *io_u)
-{
- int ret;
-
- fio_ro_check(td, io_u);
-
- ret = fio_binject_doio(td, io_u);
-
- if (ret < 0)
- io_u->error = errno;
-
- if (io_u->error) {
- td_verror(td, io_u->error, "xfer");
- return FIO_Q_COMPLETED;
- }
-
- return ret;
-}
-
-static struct io_u *fio_binject_event(struct thread_data *td, int event)
-{
- struct binject_data *bd = td->io_ops_data;
-
- return bd->events[event];
-}
-
-static int binject_open_ctl(struct thread_data *td)
-{
- int fd;
-
- fd = open("/dev/binject-ctl", O_RDWR);
- if (fd < 0)
- td_verror(td, errno, "open binject-ctl");
-
- return fd;
-}
-
-static void binject_unmap_dev(struct thread_data *td, struct binject_file *bf)
-{
- struct b_ioctl_cmd bic;
- int fdb;
-
- if (bf->fd >= 0) {
- close(bf->fd);
- bf->fd = -1;
- }
-
- fdb = binject_open_ctl(td);
- if (fdb < 0)
- return;
-
- bic.minor = bf->minor;
-
- if (ioctl(fdb, B_IOCTL_DEL, &bic) < 0)
- td_verror(td, errno, "binject dev unmap");
-
- close(fdb);
-}
-
-static int binject_map_dev(struct thread_data *td, struct binject_file *bf,
- int fd)
-{
- struct b_ioctl_cmd bic;
- char name[80];
- struct stat sb;
- int fdb, dev_there, loops;
-
- fdb = binject_open_ctl(td);
- if (fdb < 0)
- return 1;
-
- bic.fd = fd;
-
- if (ioctl(fdb, B_IOCTL_ADD, &bic) < 0) {
- td_verror(td, errno, "binject dev map");
- close(fdb);
- return 1;
- }
-
- bf->minor = bic.minor;
-
- sprintf(name, "/dev/binject%u", bf->minor);
-
- /*
- * Wait for udev to create the node...
- */
- dev_there = loops = 0;
- do {
- if (!stat(name, &sb)) {
- dev_there = 1;
- break;
- }
-
- usleep(10000);
- } while (++loops < 100);
-
- close(fdb);
-
- if (!dev_there) {
- log_err("fio: timed out waiting for binject dev\n");
- goto err_unmap;
- }
-
- bf->fd = open(name, O_RDWR);
- if (bf->fd < 0) {
- td_verror(td, errno, "binject dev open");
-err_unmap:
- binject_unmap_dev(td, bf);
- return 1;
- }
-
- return 0;
-}
-
-static int fio_binject_close_file(struct thread_data *td, struct fio_file *f)
-{
- struct binject_file *bf = FILE_ENG_DATA(f);
-
- if (bf) {
- binject_unmap_dev(td, bf);
- free(bf);
- FILE_SET_ENG_DATA(f, NULL);
- return generic_close_file(td, f);
- }
-
- return 0;
-}
-
-static int fio_binject_open_file(struct thread_data *td, struct fio_file *f)
-{
- struct binject_file *bf;
- unsigned int bs;
- int ret;
-
- ret = generic_open_file(td, f);
- if (ret)
- return 1;
-
- if (f->filetype != FIO_TYPE_BLOCK) {
- log_err("fio: binject only works with block devices\n");
- goto err_close;
- }
- if (ioctl(f->fd, BLKSSZGET, &bs) < 0) {
- td_verror(td, errno, "BLKSSZGET");
- goto err_close;
- }
-
- bf = malloc(sizeof(*bf));
- bf->bs = bs;
- bf->minor = bf->fd = -1;
- FILE_SET_ENG_DATA(f, bf);
-
- if (binject_map_dev(td, bf, f->fd)) {
-err_close:
- ret = generic_close_file(td, f);
- return 1;
- }
-
- return 0;
-}
-
-static void fio_binject_cleanup(struct thread_data *td)
-{
- struct binject_data *bd = td->io_ops_data;
-
- if (bd) {
- free(bd->events);
- free(bd->cmds);
- free(bd->fd_flags);
- free(bd->pfds);
- free(bd);
- }
-}
-
-static int fio_binject_init(struct thread_data *td)
-{
- struct binject_data *bd;
-
- bd = malloc(sizeof(*bd));
- memset(bd, 0, sizeof(*bd));
-
- bd->cmds = malloc(td->o.iodepth * sizeof(struct b_user_cmd));
- memset(bd->cmds, 0, td->o.iodepth * sizeof(struct b_user_cmd));
-
- bd->events = malloc(td->o.iodepth * sizeof(struct io_u *));
- memset(bd->events, 0, td->o.iodepth * sizeof(struct io_u *));
-
- bd->pfds = malloc(sizeof(struct pollfd) * td->o.nr_files);
- memset(bd->pfds, 0, sizeof(struct pollfd) * td->o.nr_files);
-
- bd->fd_flags = malloc(sizeof(int) * td->o.nr_files);
- memset(bd->fd_flags, 0, sizeof(int) * td->o.nr_files);
-
- td->io_ops_data = bd;
- return 0;
-}
-
-static struct ioengine_ops ioengine = {
- .name = "binject",
- .version = FIO_IOOPS_VERSION,
- .init = fio_binject_init,
- .prep = fio_binject_prep,
- .queue = fio_binject_queue,
- .getevents = fio_binject_getevents,
- .event = fio_binject_event,
- .cleanup = fio_binject_cleanup,
- .open_file = fio_binject_open_file,
- .close_file = fio_binject_close_file,
- .get_file_size = generic_get_file_size,
- .flags = FIO_RAWIO | FIO_BARRIER | FIO_MEMALIGN,
-};
-
-#else /* FIO_HAVE_BINJECT */
-
-/*
- * When we have a proper configure system in place, we simply wont build
- * and install this io engine. For now install a crippled version that
- * just complains and fails to load.
- */
-static int fio_binject_init(struct thread_data fio_unused *td)
-{
- log_err("fio: ioengine binject not available\n");
- return 1;
-}
-
-static struct ioengine_ops ioengine = {
- .name = "binject",
- .version = FIO_IOOPS_VERSION,
- .init = fio_binject_init,
-};
-
-#endif
-
-static void fio_init fio_binject_register(void)
-{
- register_ioengine(&ioengine);
-}
-
-static void fio_exit fio_binject_unregister(void)
-{
- unregister_ioengine(&ioengine);
-}
static int fio_gf_io_u_init(struct thread_data *td, struct io_u *io_u)
{
+ struct fio_gf_iou *io;
dprint(FD_FILE, "%s\n", __FUNCTION__);
-
- if (!io_u->engine_data) {
- struct fio_gf_iou *io;
-
- io = malloc(sizeof(struct fio_gf_iou));
- if (!io) {
- td_verror(td, errno, "malloc");
- return 1;
- }
- io->io_complete = 0;
- io->io_u = io_u;
- io_u->engine_data = io;
- }
+
+ io = malloc(sizeof(struct fio_gf_iou));
+ if (!io) {
+ td_verror(td, errno, "malloc");
+ return 1;
+ }
+ io->io_complete = 0;
+ io->io_u = io_u;
+ io_u->engine_data = io;
return 0;
}
if (f->filetype == FIO_TYPE_BLOCK) {
ret = fio_sgio_ioctl_doio(td, f, io_u);
- td->error = io_u->error;
+ td_verror(td, io_u->error, __func__);
} else {
ret = fio_sgio_rw_doio(f, io_u, do_sync);
if (do_sync)
- td->error = io_u->error;
+ td_verror(td, io_u->error, __func__);
}
return ret;
str += sprintf(str, "%02uh:", h);
str += sprintf(str, "%02um:", m);
- str += sprintf(str, "%02us", s);
+ sprintf(str, "%02us", s);
}
/*
free(iops_str[ddir]);
}
}
- p += sprintf(p, "\r");
+ sprintf(p, "\r");
printf("%s", output);
} else if (td_ioengine_flagged(td, FIO_DISKLESSIO)) {
dprint(FD_IO, "invalidate not supported by ioengine %s\n",
td->io_ops->name);
- ret = 0;
} else if (f->filetype == FIO_TYPE_FILE) {
dprint(FD_IO, "declare unneeded cache %s: %llu/%llu\n",
f->file_name, off, len);
log_err("fio: only root may flush block "
"devices. Cache flush bypassed!\n");
}
- ret = 0;
}
if (ret < 0)
errval = errno;
} else if (f->filetype == FIO_TYPE_CHAR ||
f->filetype == FIO_TYPE_PIPE) {
dprint(FD_IO, "invalidate not supported %s\n", f->file_name);
- ret = 0;
}
/*
__TD_F_READ_IOLOG,
__TD_F_REFILL_BUFFERS,
__TD_F_SCRAMBLE_BUFFERS,
- __TD_F_VER_NONE,
+ __TD_F_DO_VERIFY,
__TD_F_PROFILE_OPS,
__TD_F_COMPRESS,
__TD_F_COMPRESS_LOG,
TD_F_READ_IOLOG = 1U << __TD_F_READ_IOLOG,
TD_F_REFILL_BUFFERS = 1U << __TD_F_REFILL_BUFFERS,
TD_F_SCRAMBLE_BUFFERS = 1U << __TD_F_SCRAMBLE_BUFFERS,
- TD_F_VER_NONE = 1U << __TD_F_VER_NONE,
+ TD_F_DO_VERIFY = 1U << __TD_F_DO_VERIFY,
TD_F_PROFILE_OPS = 1U << __TD_F_PROFILE_OPS,
TD_F_COMPRESS = 1U << __TD_F_COMPRESS,
TD_F_COMPRESS_LOG = 1U << __TD_F_COMPRESS_LOG,
fio_option_is_set(o, zero_buffers)))
td->flags |= TD_F_SCRAMBLE_BUFFERS;
if (o->verify != VERIFY_NONE)
- td->flags |= TD_F_VER_NONE;
+ td->flags |= TD_F_DO_VERIFY;
if (o->verify_async || o->io_submit_mode == IO_MODE_OFFLOAD)
td->flags |= TD_F_NEED_LOCK;
if (p[0] == '[') {
if (nested) {
log_err("No new sections in included files\n");
- return 1;
+ ret = 1;
+ goto out;
}
skip_fgets = 1;
/*
* Return an io_u to be processed. Gets a buflen and offset, sets direction,
- * etc. The returned io_u is fully ready to be prepped and submitted.
+ * etc. The returned io_u is fully ready to be prepped, populated and submitted.
*/
struct io_u *get_io_u(struct thread_data *td)
{
td->o.min_bs[DDIR_WRITE],
io_u->buflen);
} else if ((td->flags & TD_F_SCRAMBLE_BUFFERS) &&
- !(td->flags & TD_F_COMPRESS))
+ !(td->flags & TD_F_COMPRESS) &&
+ !(td->flags & TD_F_DO_VERIFY))
do_scramble = 1;
- if (td->flags & TD_F_VER_NONE) {
- populate_verify_io_u(td, io_u);
- do_scramble = 0;
- }
} else if (io_u->ddir == DDIR_READ) {
/*
* Reset the buf_filled parameters so next time if the
#ifdef CONFIG_SOLARISAIO
aio_result_t resultp;
#endif
-#ifdef FIO_HAVE_BINJECT
- struct b_user_cmd buc;
-#endif
#ifdef CONFIG_RDMA
struct ibv_mr *mr;
#endif
struct iolog_compress ic;
z_stream stream;
struct stat sb;
- ssize_t ret;
+ size_t ret;
size_t total;
void *buf;
FILE *f;
ic.seq = 1;
ret = fread(ic.buf, ic.len, 1, f);
- if (ret < 0) {
+ if (ret == 0 && ferror(f)) {
perror("fread");
fclose(f);
free(buf);
return 1;
- } else if (ret != 1) {
+ } else if (ferror(f) || (!feof(f) && ret != 1)) {
log_err("fio: short read on reading log\n");
fclose(f);
free(buf);
}
axmap->nr_levels = levels;
- axmap->levels = malloc(axmap->nr_levels * sizeof(struct axmap_level));
+ axmap->levels = calloc(axmap->nr_levels, sizeof(struct axmap_level));
axmap->nr_bits = nr_bits;
for (i = 0; i < axmap->nr_levels; i++) {
return 0;
}
-static int rw_verify(struct fio_option *o, void *data)
+static int rw_verify(const struct fio_option *o, void *data)
{
struct thread_data *td = cb_data_to_td(data);
return 0;
}
-static int gtod_cpu_verify(struct fio_option *o, void *data)
+static int gtod_cpu_verify(const struct fio_option *o, void *data)
{
#ifndef FIO_HAVE_CPU_AFFINITY
struct thread_data *td = cb_data_to_td(data);
.help = "GUASI IO engine",
},
#endif
-#ifdef FIO_HAVE_BINJECT
- { .ival = "binject",
- .help = "binject direct inject block engine",
- },
-#endif
#ifdef CONFIG_RDMA
{ .ival = "rdma",
.help = "RDMA IO engine",
opts_copy = dup_and_sub_options(opts, num_opts);
for (ret = 0, i = 0, unknown = 0; i < num_opts; i++) {
- struct fio_option *o;
+ const struct fio_option *o;
int newret = parse_option(opts_copy[i], opts[i], fio_options,
&o, &td->o, &td->opt_list);
opts = opts_copy;
}
for (i = 0; i < num_opts; i++) {
- struct fio_option *o = NULL;
+ const struct fio_option *o = NULL;
int newret = 1;
if (!opts_copy[i])
ret = parse_cmd_option(opt, val, fio_options, &td->o, &td->opt_list);
if (!ret) {
- struct fio_option *o;
+ const struct fio_option *o;
- o = find_option(fio_options, opt);
+ o = find_option_c(fio_options, opt);
if (o)
fio_option_mark_set(&td->o, o);
}
return kb_base;
}
-int add_option(struct fio_option *o)
+int add_option(const struct fio_option *o)
{
struct fio_option *__o;
int opt_index = 0;
return false;
}
-void fio_option_mark_set(struct thread_options *o, struct fio_option *opt)
+void fio_option_mark_set(struct thread_options *o, const struct fio_option *opt)
{
unsigned int opt_off, index, offset;
#include "parse.h"
#include "lib/types.h"
-int add_option(struct fio_option *);
+int add_option(const struct fio_option *);
void invalidate_profile_options(const char *);
extern char *exec_profile;
__r; \
})
-extern void fio_option_mark_set(struct thread_options *, struct fio_option *);
+extern void fio_option_mark_set(struct thread_options *,
+ const struct fio_option *);
-static inline bool o_match(struct fio_option *o, const char *opt)
+static inline bool o_match(const struct fio_option *o, const char *opt)
{
if (!strcmp(o->name, opt))
return true;
}
extern struct fio_option *find_option(struct fio_option *, const char *);
+extern const struct fio_option *
+find_option_c(const struct fio_option *, const char *);
extern struct fio_option *fio_option_find(const char *);
extern unsigned int fio_get_kb_base(void *);
+++ /dev/null
-#ifndef BINJECT_H
-#define BINJECT_H
-
-#include <linux/types.h>
-
-#define BINJECT_MAGIC 0x89
-#define BINJECT_VER 0x01
-#define BINJECT_MAGIC_SHIFT 8
-#define BINJECT_VER_MASK ((1 << BINJECT_MAGIC_SHIFT) - 1)
-
-struct b_user_cmd {
- __u16 magic; /* INPUT */
- __u16 type; /* INPUT */
- __u32 error; /* OUTPUT */
- __u32 flags; /* INPUT */
- __u32 len; /* INPUT */
- __u64 offset; /* INPUT */
- __u64 buf; /* INPUT */
- __u64 usr_ptr; /* PASSED THROUGH */
- __u64 nsec; /* OUTPUT */
-};
-
-struct b_ioctl_cmd {
- int fd;
- int minor;
-};
-
-#define BINJECT_IOCTL_CHR 'J'
-#define B_IOCTL_ADD _IOWR(BINJECT_IOCTL_CHR, 1, struct b_ioctl_cmd)
-#define B_IOCTL_DEL _IOWR(BINJECT_IOCTL_CHR, 2, struct b_ioctl_cmd)
-
-enum {
- B_TYPE_READ = 0,
- B_TYPE_WRITE,
- B_TYPE_DISCARD,
- B_TYPE_READVOID,
- B_TYPE_WRITEZERO,
- B_TYPE_READBARRIER,
- B_TYPE_WRITEBARRIER,
- B_TYPE_NR
-};
-
-enum {
- __B_FLAG_SYNC = 0,
- __B_FLAG_UNPLUG,
- __B_FLAG_NOIDLE,
- __B_FLAG_BARRIER,
- __B_FLAG_META,
- __B_FLAG_RAHEAD,
- __B_FLAG_FAILFAST_DEV,
- __B_FLAG_FAILFAST_TRANSPORT,
- __B_FLAG_FAILFAST_DRIVER,
- __B_FLAG_NR,
-
- B_FLAG_SYNC = 1 << __B_FLAG_SYNC,
- B_FLAG_UNPLUG = 1 << __B_FLAG_UNPLUG,
- B_FLAG_NOIDLE = 1 << __B_FLAG_NOIDLE,
- B_FLAG_BARRIER = 1 << __B_FLAG_BARRIER,
- B_FLAG_META = 1 << __B_FLAG_META,
- B_FLAG_RAHEAD = 1 << __B_FLAG_RAHEAD,
- B_FLAG_FAILFAST_DEV = 1 << __B_FLAG_FAILFAST_DEV,
- B_FLAG_FAILFAST_TRANSPORT = 1 << __B_FLAG_FAILFAST_TRANSPORT,
- B_FLAG_FAILFAST_DRIVER = 1 << __B_FLAG_FAILFAST_DRIVER,
-};
-
-static inline void binject_buc_set_magic(struct b_user_cmd *buc)
-{
- buc->magic = (BINJECT_MAGIC << BINJECT_MAGIC_SHIFT) | BINJECT_VER;
-}
-
-#endif
#include <asm/byteorder.h>
#include "./os-linux-syscall.h"
-#include "binject.h"
#include "../file.h"
#ifndef __has_builtin // Optional of course.
#include <sys/sysctl.h>
#include <sys/statvfs.h>
#include <sys/diskslice.h>
-#include <sys/ioctl_compat.h>
#include <sys/usched.h>
#include <sys/resource.h>
+/* API changed during "5.3 development" */
+#if __DragonFly_version < 500302
+#include <sys/ioctl_compat.h>
+#define DAIOCTRIM IOCTLTRIM
+#else
+#include <bus/cam/scsi/scsi_daio.h>
+#endif
+
#include "../file.h"
#include "../lib/types.h"
range[0] = start;
range[1] = len;
- if (!ioctl(f->fd, IOCTLTRIM, range))
+ if (!ioctl(f->fd, DAIOCTRIM, range))
return 0;
return errno;
#include <linux/fs.h>
#include <scsi/sg.h>
+#ifdef ARCH_HAVE_CRC_CRYPTO
+#include <sys/auxv.h>
+#ifndef HWCAP_CRC32
+#define HWCAP_CRC32 (1 << 7)
+#endif /* HWCAP_CRC32 */
+#endif /* ARCH_HAVE_CRC_CRYPTO */
+
#include "./os-linux-syscall.h"
-#include "binject.h"
#include "../file.h"
#ifndef __has_builtin // Optional of course.
#define FIO_HAVE_CGROUPS
#define FIO_HAVE_FS_STAT
#define FIO_HAVE_TRIM
-#define FIO_HAVE_BINJECT
#define FIO_HAVE_GETTID
#define FIO_USE_GENERIC_INIT_RANDOM_STATE
#define FIO_HAVE_PWRITEV2
}
#endif
+#define FIO_HAVE_CPU_HAS
+static inline bool os_cpu_has(cpu_features feature)
+{
+ bool have_feature;
+ unsigned long fio_unused hwcap;
+
+ switch (feature) {
+#ifdef ARCH_HAVE_CRC_CRYPTO
+ case CPU_ARM64_CRC32C:
+ hwcap = getauxval(AT_HWCAP);
+ have_feature = (hwcap & HWCAP_CRC32) != 0;
+ break;
+#endif
+ default:
+ have_feature = false;
+ }
+
+ return have_feature;
+}
+
#endif
os_nr,
};
+typedef enum {
+ CPU_ARM64_CRC32C,
+} cpu_features;
+
/* IWYU pragma: begin_exports */
#if defined(__ANDROID__)
#include "os-android.h"
# define FIO_HAVE_ANY_FALLOCATE
#endif
+#ifndef FIO_HAVE_CPU_HAS
+static inline bool os_cpu_has(cpu_features feature)
+{
+ return false;
+}
+#endif
+
#endif
"OPT_UNSUPPORTED",
};
-static struct fio_option *__fio_options;
+static const struct fio_option *__fio_options;
static int vp_cmp(const void *p1, const void *p2)
{
return strlen(vp2->ival) - strlen(vp1->ival);
}
-static void posval_sort(struct fio_option *o, struct value_pair *vpmap)
+static void posval_sort(const struct fio_option *o, struct value_pair *vpmap)
{
const struct value_pair *vp;
int entries;
qsort(vpmap, entries, sizeof(struct value_pair), vp_cmp);
}
-static void show_option_range(struct fio_option *o,
+static void show_option_range(const struct fio_option *o,
size_t (*logger)(const char *format, ...))
{
if (o->type == FIO_OPT_FLOAT_LIST) {
- if (o->minfp == DBL_MIN && o->maxfp == DBL_MAX)
+ const char *sep = "";
+ if (!o->minfp && !o->maxfp)
return;
- logger("%20s: min=%f", "range", o->minfp);
+ logger("%20s: ", "range");
+ if (o->minfp != DBL_MIN) {
+ logger("min=%f", o->minfp);
+ sep = ", ";
+ }
if (o->maxfp != DBL_MAX)
- logger(", max=%f", o->maxfp);
+ logger("%smax=%f", sep, o->maxfp);
logger("\n");
} else if (!o->posval[0].ival) {
if (!o->minval && !o->maxval)
}
}
-static void show_option_values(struct fio_option *o)
+static void show_option_values(const struct fio_option *o)
{
int i;
log_info("\n");
}
-static void show_option_help(struct fio_option *o, int is_err)
+static void show_option_help(const struct fio_option *o, int is_err)
{
const char *typehelp[] = {
"invalid",
*ptr = (val); \
} while (0)
-static const char *opt_type_name(struct fio_option *o)
+static const char *opt_type_name(const struct fio_option *o)
{
compiletime_assert(ARRAY_SIZE(opt_type_names) - 1 == FIO_OPT_UNSUPPORTED,
"opt_type_names[] index");
return "OPT_UNKNOWN?";
}
-static int __handle_option(struct fio_option *o, const char *ptr, void *data,
- int first, int more, int curr)
+static int __handle_option(const struct fio_option *o, const char *ptr,
+ void *data, int first, int more, int curr)
{
int il=0, *ilp;
fio_fp64_t *flp;
log_err("not a floating point value: %s\n", ptr);
return 1;
}
- if (uf > o->maxfp) {
- log_err("value out of range: %f"
- " (range max: %f)\n", uf, o->maxfp);
- return 1;
- }
- if (uf < o->minfp) {
- log_err("value out of range: %f"
- " (range min: %f)\n", uf, o->minfp);
- return 1;
+ if (o->minfp || o->maxfp) {
+ if (uf > o->maxfp) {
+ log_err("value out of range: %f"
+ " (range max: %f)\n", uf, o->maxfp);
+ return 1;
+ }
+ if (uf < o->minfp) {
+ log_err("value out of range: %f"
+ " (range min: %f)\n", uf, o->minfp);
+ return 1;
+ }
}
flp = td_var(data, o, o->off1);
return ret;
}
-static int handle_option(struct fio_option *o, const char *__ptr, void *data)
+static int handle_option(const struct fio_option *o, const char *__ptr,
+ void *data)
{
char *o_ptr, *ptr, *ptr2;
int ret, done;
return NULL;
}
+const struct fio_option *
+find_option_c(const struct fio_option *options, const char *opt)
+{
+ return find_option((struct fio_option *)options, opt);
+}
-static struct fio_option *get_option(char *opt,
- struct fio_option *options, char **post)
+static const struct fio_option *
+get_option(char *opt, const struct fio_option *options, char **post)
{
- struct fio_option *o;
+ const struct fio_option *o;
char *ret;
ret = strchr(opt, '=');
ret = opt;
(*post)++;
strip_blank_end(ret);
- o = find_option(options, ret);
+ o = find_option_c(options, ret);
} else {
- o = find_option(options, opt);
+ o = find_option_c(options, opt);
*post = NULL;
}
static int opt_cmp(const void *p1, const void *p2)
{
- struct fio_option *o;
+ const struct fio_option *o;
char *s, *foo;
int prio1, prio2;
return prio2 - prio1;
}
-void sort_options(char **opts, struct fio_option *options, int num_opts)
+void sort_options(char **opts, const struct fio_option *options, int num_opts)
{
__fio_options = options;
qsort(opts, num_opts, sizeof(char *), opt_cmp);
__fio_options = NULL;
}
-static void add_to_dump_list(struct fio_option *o, struct flist_head *dump_list,
- const char *post)
+static void add_to_dump_list(const struct fio_option *o,
+ struct flist_head *dump_list, const char *post)
{
struct print_option *p;
}
int parse_cmd_option(const char *opt, const char *val,
- struct fio_option *options, void *data,
+ const struct fio_option *options, void *data,
struct flist_head *dump_list)
{
- struct fio_option *o;
+ const struct fio_option *o;
- o = find_option(options, opt);
+ o = find_option_c(options, opt);
if (!o) {
log_err("Bad option <%s>\n", opt);
return 1;
return 0;
}
-int parse_option(char *opt, const char *input,
- struct fio_option *options, struct fio_option **o, void *data,
+int parse_option(char *opt, const char *input, const struct fio_option *options,
+ const struct fio_option **o, void *data,
struct flist_head *dump_list)
{
char *post;
return distance <= len;
}
-static struct fio_option *find_child(struct fio_option *options,
- struct fio_option *o)
+static const struct fio_option *find_child(const struct fio_option *options,
+ const struct fio_option *o)
{
- struct fio_option *__o;
+ const struct fio_option *__o;
for (__o = options + 1; __o->name; __o++)
if (__o->parent && !strcmp(__o->parent, o->name))
return NULL;
}
-static void __print_option(struct fio_option *o, struct fio_option *org,
+static void __print_option(const struct fio_option *o,
+ const struct fio_option *org,
int level)
{
char name[256], *p;
if (!o)
return;
- if (!org)
- org = o;
p = name;
depth = level;
log_info("%-24s: %s\n", name, o->help);
}
-static void print_option(struct fio_option *o)
+static void print_option(const struct fio_option *o)
{
- struct fio_option *parent;
- struct fio_option *__o;
+ const struct fio_option *parent;
+ const struct fio_option *__o;
unsigned int printed;
unsigned int level;
} while (printed);
}
-int show_cmd_help(struct fio_option *options, const char *name)
+int show_cmd_help(const struct fio_option *options, const char *name)
{
- struct fio_option *o, *closest;
+ const struct fio_option *o, *closest;
unsigned int best_dist = -1U;
int found = 0;
int show_all = 0;
/*
* Handle parsing of default parameters.
*/
-void fill_default_options(void *data, struct fio_option *options)
+void fill_default_options(void *data, const struct fio_option *options)
{
- struct fio_option *o;
+ const struct fio_option *o;
dprint(FD_PARSE, "filling default options\n");
if (!o->maxval)
o->maxval = UINT_MAX;
}
- if (o->type == FIO_OPT_FLOAT_LIST) {
- o->minfp = DBL_MIN;
- o->maxfp = DBL_MAX;
- }
if (o->type == FIO_OPT_STR_SET && o->def && !o->no_warn_def) {
log_err("Option %s: string set option with"
" default will always be true\n", o->name);
}
}
-void options_mem_dupe(struct fio_option *options, void *data)
+void options_mem_dupe(const struct fio_option *options, void *data)
{
- struct fio_option *o;
+ const struct fio_option *o;
char **ptr;
dprint(FD_PARSE, "dup options\n");
}
}
-void options_free(struct fio_option *options, void *data)
+void options_free(const struct fio_option *options, void *data)
{
- struct fio_option *o;
+ const struct fio_option *o;
char **ptr;
dprint(FD_PARSE, "free options\n");
int hide_on_set; /* hide on set, not on unset */
const char *inverse; /* if set, apply opposite action to this option */
struct fio_option *inv_opt; /* cached lookup */
- int (*verify)(struct fio_option *, void *);
+ int (*verify)(const struct fio_option *, void *);
const char *prof_name; /* only valid for specific profile */
void *prof_opts;
uint64_t category; /* what type of option */
int no_free;
};
-extern int parse_option(char *, const char *, struct fio_option *, struct fio_option **, void *, struct flist_head *);
-extern void sort_options(char **, struct fio_option *, int);
-extern int parse_cmd_option(const char *t, const char *l, struct fio_option *, void *, struct flist_head *);
-extern int show_cmd_help(struct fio_option *, const char *);
-extern void fill_default_options(void *, struct fio_option *);
+extern int parse_option(char *, const char *, const struct fio_option *,
+ const struct fio_option **, void *,
+ struct flist_head *);
+extern void sort_options(char **, const struct fio_option *, int);
+extern int parse_cmd_option(const char *t, const char *l,
+ const struct fio_option *, void *,
+ struct flist_head *);
+extern int show_cmd_help(const struct fio_option *, const char *);
+extern void fill_default_options(void *, const struct fio_option *);
extern void options_init(struct fio_option *);
-extern void options_mem_dupe(struct fio_option *, void *);
-extern void options_free(struct fio_option *, void *);
+extern void options_mem_dupe(const struct fio_option *, void *);
+extern void options_free(const struct fio_option *, void *);
extern void strip_blank_front(char **);
extern void strip_blank_end(char *);
typedef int (fio_opt_int_fn)(void *, int *);
struct thread_options;
-static inline void *td_var(void *to, struct fio_option *o, unsigned int offset)
+static inline void *td_var(void *to, const struct fio_option *o,
+ unsigned int offset)
{
void *ret;
else
ret = to;
- return (char *) ret + offset;
+ return ret + offset;
}
static inline int parse_is_percent(unsigned long long val)
.events = POLLIN,
};
- ret = 0;
do {
int timeout = 1000;
if (len > 1)
qsort((void *)plist, len, sizeof(plist[0]), double_cmp);
- nr_uninit = 0;
/* Start only after the uninit entries end */
for (nr_uninit = 0;
nr_uninit < nr_block_infos
int i;
uint64_t sum;
+ if (!ts->ss_dur)
+ return 0;
+
for (i = 0, sum = 0; i < ts->ss_dur; i++)
sum += ts->ss_bw_data[i];
int i;
uint64_t sum;
+ if (!ts->ss_dur)
+ return 0;
+
for (i = 0, sum = 0; i < ts->ss_dur; i++)
sum += ts->ss_iops_data[i];