fusion-aw-sync: fixup GPL disclaimer
[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
25#ifdef FIO_HAVE_FUSION_AW
26
27#include <vsl_dp_experimental/vectored_write.h>
28
29/* Fix sector size to 512 bytes independent of actual sector size, just like
30 * the linux kernel. */
31#define SECTOR_SHIFT 9
32#define SECTOR_SIZE (1U<<SECTOR_SHIFT)
33
34struct acs_file_data {
35 struct vsl_iovec iov[IO_VECTOR_LIMIT];
36};
37
38static int queue(struct thread_data *td, struct io_u *io_u)
39{
40 int rc;
41 int iov_index;
42 off_t offset;
43 char *xfer_buf;
44 size_t xfer_buflen;
45 struct acs_file_data *d = io_u->file->file_data;
46
47 if (io_u->ddir != DDIR_WRITE) {
48 td_vmsg(td, -EIO, "only writes supported", "io_u->ddir");
49 rc = -EIO;
50 goto out;
51 }
52 if (io_u->xfer_buflen > IO_SIZE_MAX) {
53 td_vmsg(td, -EIO, "data too big", "io_u->xfer_buflen");
54 rc = -EIO;
55 goto out;
56 }
57 if (io_u->xfer_buflen & (SECTOR_SIZE - 1)) {
58 td_vmsg(td, -EIO, "unaligned data size", "io_u->xfer_buflen");
59 rc = -EIO;
60 goto out;
61 }
62
63 /* Chop up the write into minimal number of iovec's necessary */
64 iov_index = 0;
65 offset = io_u->offset;
66 xfer_buf = io_u->xfer_buf;
67 xfer_buflen = io_u->xfer_buflen;
68 while (xfer_buflen) {
69 struct vsl_iovec *iov = &d->iov[iov_index++];
70
71 iov->iov_len = xfer_buflen > IO_VECTOR_MAX_SIZE ?
72 IO_VECTOR_MAX_SIZE : xfer_buflen;
73 iov->iov_base = (uint64_t) xfer_buf;
74 iov->sector = offset >> SECTOR_SHIFT;
75 iov->iov_flag = VSL_IOV_WRITE;
76
77 offset += iov->iov_len;
78 xfer_buf += iov->iov_len;
79 xfer_buflen -= iov->iov_len;
80 }
81 assert(xfer_buflen == 0);
82 assert(iov_index <= IO_VECTOR_LIMIT);
83
84 rc = vsl_vectored_write(io_u->file->fd, d->iov, iov_index, O_ATOMIC);
85 if (rc == -1) {
86 td_verror(td, -errno, "vsl_vectored_write");
87 rc = -EIO;
88 goto out;
89 } else {
90 io_u->error = 0;
91 io_u->file->file_pos = io_u->offset + rc;
92 rc = FIO_Q_COMPLETED;
93 }
94
95out:
96 if (rc < 0)
97 io_u->error = rc;
98
99 return rc;
100}
101
102static int open_file(struct thread_data *td, struct fio_file *f)
103{
104 int rc;
105 struct acs_file_data *d = NULL;
106
107 d = malloc(sizeof(*d));
108 if (!d) {
109 td_verror(td, -ENOMEM, "malloc");
110 rc = -ENOMEM;
111 goto error;
112 }
113 f->file_data = d;
114
115 rc = generic_open_file(td, f);
116
117out:
118 return rc;
119
120error:
121 f->fd = -1;
122 f->file_data = NULL;
123 if (d)
124 free(d);
125
126 goto out;
127}
128
129static int close_file(struct thread_data *td, struct fio_file *f)
130{
131 if (f->file_data) {
132 free(f->file_data);
133 f->file_data = NULL;
134 }
135
136 return generic_close_file(td, f);
137}
138
139static struct ioengine_ops ioengine = {
140 .name = "fusion-aw-sync",
141 .version = FIO_IOOPS_VERSION,
142 .queue = queue,
143 .open_file = open_file,
144 .close_file = close_file,
145 .get_file_size = generic_get_file_size,
146 .flags = FIO_SYNCIO | FIO_RAWIO | FIO_MEMALIGN
147};
148
149#else /* !FUSION_HAVE_FUSION_AW */
150
151static int fio_fusion_aw_eng_init(struct thread_data fio_unused *td)
152{
153 log_err("fio: fusion atomic write engine not available\n");
154 return 1;
155}
156
157static struct ioengine_ops ioengine = {
158 .name = "fusion-aw-sync",
159 .version = FIO_IOOPS_VERSION,
160 .init = fio_fusion_aw_eng_init,
161};
162
163#endif /* FUSION_HAVE_FUSION_AW */
164
165static void fio_init fio_fusion_aw_init(void)
166{
167 register_ioengine(&ioengine);
168}
169
170static void fio_exit fio_fusion_aw_exit(void)
171{
172 unregister_ioengine(&ioengine);
173}