2 * Custom fio(1) engine that submits synchronous atomic writes to file.
4 * Copyright (C) 2012 Fusion-io, Inc.
5 * Author: Santhosh Kumar Koundinya.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; under version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License version
16 * You should have received a copy of the GNU General Public License Version 2
17 * along with this program; if not see <http://www.gnu.org/licenses/>
25 #include <vsl_dp_experimental/vectored_write.h>
27 /* Fix sector size to 512 bytes independent of actual sector size, just like
28 * the linux kernel. */
29 #define SECTOR_SHIFT 9
30 #define SECTOR_SIZE (1U<<SECTOR_SHIFT)
32 struct acs_file_data {
33 struct vsl_iovec iov[IO_VECTOR_LIMIT];
36 static int queue(struct thread_data *td, struct io_u *io_u)
43 struct acs_file_data *d = io_u->file->file_data;
45 if (io_u->ddir != DDIR_WRITE) {
46 td_vmsg(td, -EIO, "only writes supported", "io_u->ddir");
50 if (io_u->xfer_buflen > IO_SIZE_MAX) {
51 td_vmsg(td, -EIO, "data too big", "io_u->xfer_buflen");
55 if (io_u->xfer_buflen & (SECTOR_SIZE - 1)) {
56 td_vmsg(td, -EIO, "unaligned data size", "io_u->xfer_buflen");
61 /* Chop up the write into minimal number of iovec's necessary */
63 offset = io_u->offset;
64 xfer_buf = io_u->xfer_buf;
65 xfer_buflen = io_u->xfer_buflen;
67 struct vsl_iovec *iov = &d->iov[iov_index++];
69 iov->iov_len = xfer_buflen > IO_VECTOR_MAX_SIZE ?
70 IO_VECTOR_MAX_SIZE : xfer_buflen;
71 iov->iov_base = (uint64_t) xfer_buf;
72 iov->sector = offset >> SECTOR_SHIFT;
73 iov->iov_flag = VSL_IOV_WRITE;
75 offset += iov->iov_len;
76 xfer_buf += iov->iov_len;
77 xfer_buflen -= iov->iov_len;
79 assert(xfer_buflen == 0);
80 assert(iov_index <= IO_VECTOR_LIMIT);
82 rc = vsl_vectored_write(io_u->file->fd, d->iov, iov_index, O_ATOMIC);
84 td_verror(td, -errno, "vsl_vectored_write");
99 static int open_file(struct thread_data *td, struct fio_file *f)
102 struct acs_file_data *d = NULL;
104 d = malloc(sizeof(*d));
106 td_verror(td, -ENOMEM, "malloc");
112 rc = generic_open_file(td, f);
126 static int close_file(struct thread_data *td, struct fio_file *f)
133 return generic_close_file(td, f);
136 static struct ioengine_ops ioengine = {
137 .name = "fusion-aw-sync",
138 .version = FIO_IOOPS_VERSION,
140 .open_file = open_file,
141 .close_file = close_file,
142 .get_file_size = generic_get_file_size,
143 .flags = FIO_SYNCIO | FIO_RAWIO | FIO_MEMALIGN
146 static void fio_init fio_fusion_aw_init(void)
148 register_ioengine(&ioengine);
151 static void fio_exit fio_fusion_aw_exit(void)
153 unregister_ioengine(&ioengine);