From 6ef63580ab6e3d73f205d05b126dbeb33e0508bc Mon Sep 17 00:00:00 2001 From: Santhosh Koundinya Date: Tue, 18 Sep 2012 23:20:21 +0200 Subject: [PATCH] Add support for Fusion-io atomic write engine Signed-off-by: Jens Axboe --- Makefile | 3 +- engines/fusion-aw.c | 176 ++++++++++++++++++++++++++++++++++++ examples/fusion-aw-sync.ini | 15 +++ 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 engines/fusion-aw.c create mode 100644 examples/fusion-aw-sync.ini diff --git a/Makefile b/Makefile index bac062c6..5e90ca26 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,8 @@ ifeq ($(UNAME), Linux) SOURCE += diskutil.c fifo.c blktrace.c helpers.c cgroup.c trim.c \ engines/libaio.c engines/posixaio.c engines/sg.c \ engines/splice.c engines/syslet-rw.c engines/guasi.c \ - engines/binject.c engines/rdma.c profiles/tiobench.c + engines/binject.c engines/rdma.c profiles/tiobench.c \ + engines/fusion-aw.c LIBS += -lpthread -ldl -lrt -laio LDFLAGS += -rdynamic endif diff --git a/engines/fusion-aw.c b/engines/fusion-aw.c new file mode 100644 index 00000000..0f9025fa --- /dev/null +++ b/engines/fusion-aw.c @@ -0,0 +1,176 @@ +/* + * Custom fio(1) engine that submits synchronous atomic writes to file. + * + * Copyright (C) 2012 Fusion-io, Inc. + * Author: Santhosh Kumar Koundinya. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; under version 2 of the License. You may obtain a copy + * of the source code for DirectFS by sending a request to Fusion-io, Inc., + * 2855 E. Cottonwood Parkway, Suite 100, Salt Lake City, UT 84121; Attention: + * Legal Department. + * + * 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 version + * 2 for more details. + * + * You should have received a copy of the GNU General Public License Version 2 + * along with this program; if not see + */ + +#include +#include + +#include "../fio.h" + +#ifdef FIO_HAVE_FUSION_AW + +#include + +/* Fix sector size to 512 bytes independent of actual sector size, just like + * the linux kernel. */ +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1U<file->file_data; + + if (io_u->ddir != DDIR_WRITE) { + td_vmsg(td, -EIO, "only writes supported", "io_u->ddir"); + rc = -EIO; + goto out; + } + if (io_u->xfer_buflen > IO_SIZE_MAX) { + td_vmsg(td, -EIO, "data too big", "io_u->xfer_buflen"); + rc = -EIO; + goto out; + } + if (io_u->xfer_buflen & (SECTOR_SIZE - 1)) { + td_vmsg(td, -EIO, "unaligned data size", "io_u->xfer_buflen"); + rc = -EIO; + goto out; + } + + /* Chop up the write into minimal number of iovec's necessary */ + iov_index = 0; + offset = io_u->offset; + xfer_buf = io_u->xfer_buf; + xfer_buflen = io_u->xfer_buflen; + while (xfer_buflen) { + struct vsl_iovec *iov = &d->iov[iov_index++]; + + iov->iov_len = xfer_buflen > IO_VECTOR_MAX_SIZE ? + IO_VECTOR_MAX_SIZE : xfer_buflen; + iov->iov_base = (uint64_t) xfer_buf; + iov->sector = offset >> SECTOR_SHIFT; + iov->iov_flag = VSL_IOV_WRITE; + + offset += iov->iov_len; + xfer_buf += iov->iov_len; + xfer_buflen -= iov->iov_len; + } + assert(xfer_buflen == 0); + assert(iov_index <= IO_VECTOR_LIMIT); + + rc = vsl_vectored_write(io_u->file->fd, d->iov, iov_index, O_ATOMIC); + if (rc == -1) { + td_verror(td, -errno, "vsl_vectored_write"); + rc = -EIO; + goto out; + } else { + io_u->error = 0; + io_u->file->file_pos = io_u->offset + rc; + rc = FIO_Q_COMPLETED; + } + +out: + if (rc < 0) + io_u->error = rc; + + return rc; +} + +static int open_file(struct thread_data *td, struct fio_file *f) +{ + int rc; + struct acs_file_data *d = NULL; + + d = malloc(sizeof(*d)); + if (!d) { + td_verror(td, -ENOMEM, "malloc"); + rc = -ENOMEM; + goto error; + } + f->file_data = d; + + rc = generic_open_file(td, f); + +out: + return rc; + +error: + f->fd = -1; + f->file_data = NULL; + if (d) + free(d); + + goto out; +} + +static int close_file(struct thread_data *td, struct fio_file *f) +{ + if (f->file_data) { + free(f->file_data); + f->file_data = NULL; + } + + return generic_close_file(td, f); +} + +static struct ioengine_ops ioengine = { + .name = "fusion-aw-sync", + .version = FIO_IOOPS_VERSION, + .queue = queue, + .open_file = open_file, + .close_file = close_file, + .get_file_size = generic_get_file_size, + .flags = FIO_SYNCIO | FIO_RAWIO | FIO_MEMALIGN +}; + +#else /* !FUSION_HAVE_FUSION_AW */ + +static int fio_fusion_aw_eng_init(struct thread_data fio_unused *td) +{ + log_err("fio: fusion atomic write engine not available\n"); + return 1; +} + +static struct ioengine_ops ioengine = { + .name = "fusion-aw-sync", + .version = FIO_IOOPS_VERSION, + .init = fio_fusion_aw_eng_init, +}; + +#endif /* FUSION_HAVE_FUSION_AW */ + +static void fio_init fio_fusion_aw_init(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_fusion_aw_exit(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/examples/fusion-aw-sync.ini b/examples/fusion-aw-sync.ini new file mode 100644 index 00000000..c4639f06 --- /dev/null +++ b/examples/fusion-aw-sync.ini @@ -0,0 +1,15 @@ +# Example Job File that randomly writes 8k worth of data atomically for +# 60 seconds. +[rw_aw_file_sync] +rw=randwrite +ioengine=fusion-aw-sync +blocksize=8k +blockalign=8k + +filename=/mnt/fs/file +randrepeat=1 +fallocate=none +direct=1 +invalidate=0 +runtime=60 +time_based -- 2.25.1