flow: quiesce pending IO before sleep
[fio.git] / engines / fusion-aw.c
CommitLineData
6ef63580
SK
1/*
2 * Custom fio(1) engine that submits synchronous atomic writes to file.
3 *
4 * Copyright (C) 2012 Fusion-io, Inc.
5 * Author: Santhosh Kumar Koundinya.
6 *
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
15a6f166 9 * Software Foundation; under version 2 of the License.
6ef63580
SK
10 *
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
14 * 2 for more details.
15 *
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/>
18 */
19
20#include <stdlib.h>
21#include <stdint.h>
22
23#include "../fio.h"
24
99db6564 25#include <nvm/vectored_write.h>
6ef63580
SK
26
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)
31
c11a9ddf 32struct acs_engine_data {
6ef63580
SK
33 struct vsl_iovec iov[IO_VECTOR_LIMIT];
34};
35
36static int queue(struct thread_data *td, struct io_u *io_u)
37{
38 int rc;
39 int iov_index;
40 off_t offset;
41 char *xfer_buf;
42 size_t xfer_buflen;
c11a9ddf
JA
43 struct acs_engine_data *d =
44 (struct acs_engine_data *) io_u->file->engine_data;
6ef63580
SK
45
46 if (io_u->ddir != DDIR_WRITE) {
47 td_vmsg(td, -EIO, "only writes supported", "io_u->ddir");
48 rc = -EIO;
49 goto out;
50 }
51 if (io_u->xfer_buflen > IO_SIZE_MAX) {
52 td_vmsg(td, -EIO, "data too big", "io_u->xfer_buflen");
53 rc = -EIO;
54 goto out;
55 }
56 if (io_u->xfer_buflen & (SECTOR_SIZE - 1)) {
57 td_vmsg(td, -EIO, "unaligned data size", "io_u->xfer_buflen");
58 rc = -EIO;
59 goto out;
60 }
61
62 /* Chop up the write into minimal number of iovec's necessary */
63 iov_index = 0;
64 offset = io_u->offset;
65 xfer_buf = io_u->xfer_buf;
66 xfer_buflen = io_u->xfer_buflen;
67 while (xfer_buflen) {
68 struct vsl_iovec *iov = &d->iov[iov_index++];
69
70 iov->iov_len = xfer_buflen > IO_VECTOR_MAX_SIZE ?
71 IO_VECTOR_MAX_SIZE : xfer_buflen;
72 iov->iov_base = (uint64_t) xfer_buf;
73 iov->sector = offset >> SECTOR_SHIFT;
74 iov->iov_flag = VSL_IOV_WRITE;
75
76 offset += iov->iov_len;
77 xfer_buf += iov->iov_len;
78 xfer_buflen -= iov->iov_len;
79 }
80 assert(xfer_buflen == 0);
81 assert(iov_index <= IO_VECTOR_LIMIT);
82
83 rc = vsl_vectored_write(io_u->file->fd, d->iov, iov_index, O_ATOMIC);
84 if (rc == -1) {
85 td_verror(td, -errno, "vsl_vectored_write");
86 rc = -EIO;
87 goto out;
88 } else {
89 io_u->error = 0;
6ef63580
SK
90 rc = FIO_Q_COMPLETED;
91 }
92
93out:
94 if (rc < 0)
95 io_u->error = rc;
96
97 return rc;
98}
99
100static int open_file(struct thread_data *td, struct fio_file *f)
101{
102 int rc;
c11a9ddf 103 struct acs_engine_data *d = NULL;
6ef63580
SK
104
105 d = malloc(sizeof(*d));
106 if (!d) {
107 td_verror(td, -ENOMEM, "malloc");
108 rc = -ENOMEM;
109 goto error;
110 }
c11a9ddf 111 f->engine_data = (uintptr_t) d;
6ef63580
SK
112
113 rc = generic_open_file(td, f);
114
115out:
116 return rc;
117
118error:
119 f->fd = -1;
c11a9ddf 120 f->engine_data = 0;
6ef63580
SK
121 if (d)
122 free(d);
123
124 goto out;
125}
126
127static int close_file(struct thread_data *td, struct fio_file *f)
128{
c11a9ddf
JA
129 if (f->engine_data) {
130 free((void *) f->engine_data);
131 f->engine_data = 0;
6ef63580
SK
132 }
133
134 return generic_close_file(td, f);
135}
136
137static struct ioengine_ops ioengine = {
138 .name = "fusion-aw-sync",
139 .version = FIO_IOOPS_VERSION,
140 .queue = queue,
141 .open_file = open_file,
142 .close_file = close_file,
143 .get_file_size = generic_get_file_size,
144 .flags = FIO_SYNCIO | FIO_RAWIO | FIO_MEMALIGN
145};
146
6ef63580
SK
147static void fio_init fio_fusion_aw_init(void)
148{
149 register_ioengine(&ioengine);
150}
151
152static void fio_exit fio_fusion_aw_exit(void)
153{
154 unregister_ioengine(&ioengine);
155}