blob: 9c5037f5d11fb0391cc25eda994a44366e3297ce [file] [log] [blame]
Jens Axboe2866c822006-10-09 15:57:48 +02001/*
2 * scsi generic sg v3 io engine
3 *
4 */
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <errno.h>
9#include <assert.h>
10#include <sys/poll.h>
Jens Axboe5f350952006-11-07 15:20:59 +010011
12#include "../fio.h"
13#include "../os.h"
Jens Axboe2866c822006-10-09 15:57:48 +020014
Jens Axboe34cfcda2006-11-03 14:00:45 +010015#ifdef FIO_HAVE_SGIO
16
Jens Axboe2866c822006-10-09 15:57:48 +020017struct sgio_cmd {
18 unsigned char cdb[10];
19 int nr;
20};
21
22struct sgio_data {
23 struct sgio_cmd *cmds;
24 struct io_u **events;
25 unsigned int bs;
26};
27
28static void sgio_hdr_init(struct sgio_data *sd, struct sg_io_hdr *hdr,
29 struct io_u *io_u, int fs)
30{
31 struct sgio_cmd *sc = &sd->cmds[io_u->index];
32
33 memset(hdr, 0, sizeof(*hdr));
34 memset(sc->cdb, 0, sizeof(sc->cdb));
35
36 hdr->interface_id = 'S';
37 hdr->cmdp = sc->cdb;
38 hdr->cmd_len = sizeof(sc->cdb);
39 hdr->pack_id = io_u->index;
40 hdr->usr_ptr = io_u;
41
42 if (fs) {
43 hdr->dxferp = io_u->buf;
44 hdr->dxfer_len = io_u->buflen;
45 }
46}
47
48static int fio_sgio_ioctl_getevents(struct thread_data *td, int fio_unused min,
49 int max, struct timespec fio_unused *t)
50{
51 assert(max <= 1);
52
53 /*
54 * we can only have one finished io_u for sync io, since the depth
55 * is always 1
56 */
57 if (list_empty(&td->io_u_busylist))
58 return 0;
59
60 return 1;
61}
62
63
64static int fio_sgio_getevents(struct thread_data *td, int min, int max,
65 struct timespec fio_unused *t)
66{
Jens Axboe53cdc682006-10-18 11:50:58 +020067 struct fio_file *f = &td->files[0];
Jens Axboe2866c822006-10-09 15:57:48 +020068 struct sgio_data *sd = td->io_ops->data;
Jens Axboe53cdc682006-10-18 11:50:58 +020069 struct pollfd pfd = { .fd = f->fd, .events = POLLIN };
Jens Axboe2866c822006-10-09 15:57:48 +020070 void *buf = malloc(max * sizeof(struct sg_io_hdr));
71 int left = max, ret, events, i, r = 0, fl = 0;
72
73 /*
74 * don't block for !events
75 */
76 if (!min) {
Jens Axboe53cdc682006-10-18 11:50:58 +020077 fl = fcntl(f->fd, F_GETFL);
78 fcntl(f->fd, F_SETFL, fl | O_NONBLOCK);
Jens Axboe2866c822006-10-09 15:57:48 +020079 }
80
81 while (left) {
82 do {
83 if (!min)
84 break;
85 poll(&pfd, 1, -1);
86 if (pfd.revents & POLLIN)
87 break;
88 } while (1);
89
Jens Axboe53cdc682006-10-18 11:50:58 +020090 ret = read(f->fd, buf, left * sizeof(struct sg_io_hdr));
Jens Axboe2866c822006-10-09 15:57:48 +020091 if (ret < 0) {
92 if (errno == EAGAIN)
93 break;
94 td_verror(td, errno);
95 r = -1;
96 break;
97 } else if (!ret)
98 break;
99
100 events = ret / sizeof(struct sg_io_hdr);
101 left -= events;
102 r += events;
103
104 for (i = 0; i < events; i++) {
105 struct sg_io_hdr *hdr = (struct sg_io_hdr *) buf + i;
106
107 sd->events[i] = hdr->usr_ptr;
108 }
109 }
110
111 if (!min)
Jens Axboe53cdc682006-10-18 11:50:58 +0200112 fcntl(f->fd, F_SETFL, fl);
Jens Axboe2866c822006-10-09 15:57:48 +0200113
114 free(buf);
115 return r;
116}
117
Jens Axboe7a16dd02006-10-18 17:21:58 +0200118static int fio_sgio_ioctl_doio(struct thread_data *td,
119 struct fio_file *f, struct io_u *io_u)
Jens Axboe2866c822006-10-09 15:57:48 +0200120{
121 struct sgio_data *sd = td->io_ops->data;
122 struct sg_io_hdr *hdr = &io_u->hdr;
123
124 sd->events[0] = io_u;
125
Jens Axboe53cdc682006-10-18 11:50:58 +0200126 return ioctl(f->fd, SG_IO, hdr);
Jens Axboe2866c822006-10-09 15:57:48 +0200127}
128
Jens Axboe7a16dd02006-10-18 17:21:58 +0200129static int fio_sgio_rw_doio(struct fio_file *f, struct io_u *io_u, int sync)
Jens Axboe2866c822006-10-09 15:57:48 +0200130{
131 struct sg_io_hdr *hdr = &io_u->hdr;
132 int ret;
133
Jens Axboe53cdc682006-10-18 11:50:58 +0200134 ret = write(f->fd, hdr, sizeof(*hdr));
Jens Axboe2866c822006-10-09 15:57:48 +0200135 if (ret < 0)
136 return errno;
137
138 if (sync) {
Jens Axboe53cdc682006-10-18 11:50:58 +0200139 ret = read(f->fd, hdr, sizeof(*hdr));
Jens Axboe2866c822006-10-09 15:57:48 +0200140 if (ret < 0)
141 return errno;
142 }
143
144 return 0;
145}
146
147static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int sync)
148{
Jens Axboe53cdc682006-10-18 11:50:58 +0200149 struct fio_file *f = io_u->file;
Jens Axboe2866c822006-10-09 15:57:48 +0200150
Jens Axboe53cdc682006-10-18 11:50:58 +0200151 if (td->filetype == FIO_TYPE_BD)
152 return fio_sgio_ioctl_doio(td, f, io_u);
153
Jens Axboe7a16dd02006-10-18 17:21:58 +0200154 return fio_sgio_rw_doio(f, io_u, sync);
Jens Axboe2866c822006-10-09 15:57:48 +0200155}
156
Jens Axboe2866c822006-10-09 15:57:48 +0200157static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
158{
159 struct sg_io_hdr *hdr = &io_u->hdr;
160 struct sgio_data *sd = td->io_ops->data;
161 int nr_blocks, lba;
162
163 if (io_u->buflen & (sd->bs - 1)) {
164 log_err("read/write not sector aligned\n");
165 return EINVAL;
166 }
167
Jens Axboe2866c822006-10-09 15:57:48 +0200168 if (io_u->ddir == DDIR_READ) {
Jens Axboe87dc1ab2006-10-24 14:41:26 +0200169 sgio_hdr_init(sd, hdr, io_u, 1);
170
Jens Axboe2866c822006-10-09 15:57:48 +0200171 hdr->dxfer_direction = SG_DXFER_FROM_DEV;
172 hdr->cmdp[0] = 0x28;
Jens Axboe87dc1ab2006-10-24 14:41:26 +0200173 } else if (io_u->ddir == DDIR_WRITE) {
174 sgio_hdr_init(sd, hdr, io_u, 1);
175
Jens Axboe2866c822006-10-09 15:57:48 +0200176 hdr->dxfer_direction = SG_DXFER_TO_DEV;
177 hdr->cmdp[0] = 0x2a;
Jens Axboe87dc1ab2006-10-24 14:41:26 +0200178 } else {
179 sgio_hdr_init(sd, hdr, io_u, 0);
180
181 hdr->dxfer_direction = SG_DXFER_NONE;
182 hdr->cmdp[0] = 0x35;
Jens Axboe2866c822006-10-09 15:57:48 +0200183 }
184
Jens Axboe87dc1ab2006-10-24 14:41:26 +0200185 if (hdr->dxfer_direction != SG_DXFER_NONE) {
186 nr_blocks = io_u->buflen / sd->bs;
187 lba = io_u->offset / sd->bs;
188 hdr->cmdp[2] = (lba >> 24) & 0xff;
189 hdr->cmdp[3] = (lba >> 16) & 0xff;
190 hdr->cmdp[4] = (lba >> 8) & 0xff;
191 hdr->cmdp[5] = lba & 0xff;
192 hdr->cmdp[7] = (nr_blocks >> 8) & 0xff;
193 hdr->cmdp[8] = nr_blocks & 0xff;
194 }
195
Jens Axboe2866c822006-10-09 15:57:48 +0200196 return 0;
197}
198
199static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u)
200{
201 struct sg_io_hdr *hdr = &io_u->hdr;
202 int ret;
203
Jens Axboe87dc1ab2006-10-24 14:41:26 +0200204 ret = fio_sgio_doio(td, io_u, io_u->ddir == DDIR_SYNC);
Jens Axboe2866c822006-10-09 15:57:48 +0200205
206 if (ret < 0)
207 io_u->error = errno;
208 else if (hdr->status) {
209 io_u->resid = hdr->resid;
210 io_u->error = EIO;
211 }
212
213 return io_u->error;
214}
215
216static struct io_u *fio_sgio_event(struct thread_data *td, int event)
217{
218 struct sgio_data *sd = td->io_ops->data;
219
220 return sd->events[event];
221}
222
223static int fio_sgio_get_bs(struct thread_data *td, unsigned int *bs)
224{
225 struct sgio_data *sd = td->io_ops->data;
226 struct io_u *io_u;
227 struct sg_io_hdr *hdr;
228 unsigned char buf[8];
229 int ret;
230
231 io_u = __get_io_u(td);
232 assert(io_u);
233
234 hdr = &io_u->hdr;
235 sgio_hdr_init(sd, hdr, io_u, 0);
236 memset(buf, 0, sizeof(buf));
237
238 hdr->cmdp[0] = 0x25;
239 hdr->dxfer_direction = SG_DXFER_FROM_DEV;
240 hdr->dxferp = buf;
241 hdr->dxfer_len = sizeof(buf);
242
243 ret = fio_sgio_doio(td, io_u, 1);
244 if (ret) {
245 put_io_u(td, io_u);
246 return ret;
247 }
248
249 *bs = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
250 put_io_u(td, io_u);
251 return 0;
252}
253
254static void fio_sgio_cleanup(struct thread_data *td)
255{
256 if (td->io_ops->data) {
257 free(td->io_ops->data);
258 td->io_ops->data = NULL;
259 }
260}
261
262static int fio_sgio_init(struct thread_data *td)
263{
Jens Axboe53cdc682006-10-18 11:50:58 +0200264 struct fio_file *f = &td->files[0];
Jens Axboe2866c822006-10-09 15:57:48 +0200265 struct sgio_data *sd;
266 unsigned int bs;
267 int ret;
268
269 sd = malloc(sizeof(*sd));
Jens Axboecb781c72006-11-07 14:02:48 +0100270 memset(sd, 0, sizeof(*sd));
Jens Axboe2866c822006-10-09 15:57:48 +0200271 sd->cmds = malloc(td->iodepth * sizeof(struct sgio_cmd));
Jens Axboecb781c72006-11-07 14:02:48 +0100272 memset(sd->cmds, 0, td->iodepth * sizeof(struct sgio_cmd));
Jens Axboe2866c822006-10-09 15:57:48 +0200273 sd->events = malloc(td->iodepth * sizeof(struct io_u *));
Jens Axboecb781c72006-11-07 14:02:48 +0100274 memset(sd->events, 0, td->iodepth * sizeof(struct io_u *));
Jens Axboe2866c822006-10-09 15:57:48 +0200275 td->io_ops->data = sd;
276
277 if (td->filetype == FIO_TYPE_BD) {
Jens Axboe53cdc682006-10-18 11:50:58 +0200278 if (ioctl(f->fd, BLKSSZGET, &bs) < 0) {
Jens Axboe2866c822006-10-09 15:57:48 +0200279 td_verror(td, errno);
Jens Axboecb781c72006-11-07 14:02:48 +0100280 goto err;
Jens Axboe2866c822006-10-09 15:57:48 +0200281 }
282 } else if (td->filetype == FIO_TYPE_CHAR) {
283 int version;
284
Jens Axboe53cdc682006-10-18 11:50:58 +0200285 if (ioctl(f->fd, SG_GET_VERSION_NUM, &version) < 0) {
Jens Axboe2866c822006-10-09 15:57:48 +0200286 td_verror(td, errno);
Jens Axboecb781c72006-11-07 14:02:48 +0100287 goto err;
Jens Axboe2866c822006-10-09 15:57:48 +0200288 }
289
290 ret = fio_sgio_get_bs(td, &bs);
291 if (ret)
Jens Axboecb781c72006-11-07 14:02:48 +0100292 goto err;
Jens Axboe2866c822006-10-09 15:57:48 +0200293 } else {
294 log_err("ioengine sgio only works on block devices\n");
Jens Axboecb781c72006-11-07 14:02:48 +0100295 goto err;
Jens Axboe2866c822006-10-09 15:57:48 +0200296 }
297
298 sd->bs = bs;
299
300 if (td->filetype == FIO_TYPE_BD)
301 td->io_ops->getevents = fio_sgio_ioctl_getevents;
302 else
303 td->io_ops->getevents = fio_sgio_getevents;
304
305 /*
306 * we want to do it, regardless of whether odirect is set or not
307 */
308 td->override_sync = 1;
309 return 0;
Jens Axboecb781c72006-11-07 14:02:48 +0100310err:
311 free(sd->events);
312 free(sd->cmds);
313 free(sd);
314 return 1;
Jens Axboe2866c822006-10-09 15:57:48 +0200315}
316
Jens Axboe5f350952006-11-07 15:20:59 +0100317static struct ioengine_ops ioengine = {
Jens Axboe2866c822006-10-09 15:57:48 +0200318 .name = "sg",
319 .version = FIO_IOOPS_VERSION,
320 .init = fio_sgio_init,
321 .prep = fio_sgio_prep,
322 .queue = fio_sgio_queue,
323 .getevents = fio_sgio_getevents,
324 .event = fio_sgio_event,
325 .cleanup = fio_sgio_cleanup,
Jens Axboeb2a15192006-10-18 14:10:42 +0200326 .flags = FIO_SYNCIO | FIO_RAWIO,
Jens Axboe2866c822006-10-09 15:57:48 +0200327};
Jens Axboe34cfcda2006-11-03 14:00:45 +0100328
329#else /* FIO_HAVE_SGIO */
330
331/*
332 * When we have a proper configure system in place, we simply wont build
333 * and install this io engine. For now install a crippled version that
334 * just complains and fails to load.
335 */
336static int fio_sgio_init(struct thread_data fio_unused *td)
337{
338 fprintf(stderr, "fio: sgio not available\n");
339 return 1;
340}
341
Jens Axboe5f350952006-11-07 15:20:59 +0100342static struct ioengine_ops ioengine = {
Jens Axboe34cfcda2006-11-03 14:00:45 +0100343 .name = "sgio",
344 .version = FIO_IOOPS_VERSION,
345 .init = fio_sgio_init,
346};
347
348#endif
Jens Axboe5f350952006-11-07 15:20:59 +0100349
350static void fio_init fio_sgio_register(void)
351{
352 register_ioengine(&ioengine);
353}
354
355static void fio_exit fio_sgio_unregister(void)
356{
357 unregister_ioengine(&ioengine);
358}