sg: Avoid READ CAPACITY failures
[fio.git] / engines / sg.c
1 /*
2  * sg engine
3  *
4  * IO engine that uses the Linux SG v3 interface to talk to SCSI devices
5  *
6  * This ioengine can operate in two modes:
7  *      sync    with block devices (/dev/sdX) or
8  *              with character devices (/dev/sgY) with direct=1 or sync=1
9  *      async   with character devices with direct=0 and sync=0
10  *
11  * What value does queue() return for the different cases?
12  *                              queue() return value
13  * In sync mode:
14  *  /dev/sdX            RWT     FIO_Q_COMPLETED
15  *  /dev/sgY            RWT     FIO_Q_COMPLETED
16  *   with direct=1 or sync=1
17  *
18  * In async mode:
19  *  /dev/sgY            RWT     FIO_Q_QUEUED
20  *   direct=0 and sync=0
21  *
22  * Because FIO_SYNCIO is set for this ioengine td_io_queue() will fill in
23  * issue_time *before* each IO is sent to queue()
24  *
25  * Where are the IO counting functions called for the different cases?
26  *
27  * In sync mode:
28  *  /dev/sdX (commit==NULL)
29  *   RWT
30  *    io_u_mark_depth()                 called in td_io_queue()
31  *    io_u_mark_submit/complete()       called in td_io_queue()
32  *    issue_time                        set in td_io_queue()
33  *
34  *  /dev/sgY with direct=1 or sync=1 (commit does nothing)
35  *   RWT
36  *    io_u_mark_depth()                 called in td_io_queue()
37  *    io_u_mark_submit/complete()       called in queue()
38  *    issue_time                        set in td_io_queue()
39  *  
40  * In async mode:
41  *  /dev/sgY with direct=0 and sync=0
42  *   RW: read and write operations are submitted in queue()
43  *    io_u_mark_depth()                 called in td_io_commit()
44  *    io_u_mark_submit()                called in queue()
45  *    issue_time                        set in td_io_queue()
46  *   T: trim operations are queued in queue() and submitted in commit()
47  *    io_u_mark_depth()                 called in td_io_commit()
48  *    io_u_mark_submit()                called in commit()
49  *    issue_time                        set in commit()
50  *
51  */
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <poll.h>
57
58 #include "../fio.h"
59 #include "../optgroup.h"
60
61 #ifdef FIO_HAVE_SGIO
62
63 enum {
64         FIO_SG_WRITE            = 1,
65         FIO_SG_WRITE_VERIFY     = 2,
66         FIO_SG_WRITE_SAME       = 3
67 };
68
69 struct sg_options {
70         void *pad;
71         unsigned int readfua;
72         unsigned int writefua;
73         unsigned int write_mode;
74 };
75
76 static struct fio_option options[] = {
77         {
78                 .name   = "readfua",
79                 .lname  = "sg engine read fua flag support",
80                 .type   = FIO_OPT_BOOL,
81                 .off1   = offsetof(struct sg_options, readfua),
82                 .help   = "Set FUA flag (force unit access) for all Read operations",
83                 .def    = "0",
84                 .category = FIO_OPT_C_ENGINE,
85                 .group  = FIO_OPT_G_SG,
86         },
87         {
88                 .name   = "writefua",
89                 .lname  = "sg engine write fua flag support",
90                 .type   = FIO_OPT_BOOL,
91                 .off1   = offsetof(struct sg_options, writefua),
92                 .help   = "Set FUA flag (force unit access) for all Write operations",
93                 .def    = "0",
94                 .category = FIO_OPT_C_ENGINE,
95                 .group  = FIO_OPT_G_SG,
96         },
97         {
98                 .name   = "sg_write_mode",
99                 .lname  = "specify sg write mode",
100                 .type   = FIO_OPT_STR,
101                 .off1   = offsetof(struct sg_options, write_mode),
102                 .help   = "Specify SCSI WRITE mode",
103                 .def    = "write",
104                 .posval = {
105                           { .ival = "write",
106                             .oval = FIO_SG_WRITE,
107                             .help = "Issue standard SCSI WRITE commands",
108                           },
109                           { .ival = "verify",
110                             .oval = FIO_SG_WRITE_VERIFY,
111                             .help = "Issue SCSI WRITE AND VERIFY commands",
112                           },
113                           { .ival = "same",
114                             .oval = FIO_SG_WRITE_SAME,
115                             .help = "Issue SCSI WRITE SAME commands",
116                           },
117                 },
118                 .category = FIO_OPT_C_ENGINE,
119                 .group  = FIO_OPT_G_SG,
120         },
121         {
122                 .name   = NULL,
123         },
124 };
125
126 #define MAX_10B_LBA  0xFFFFFFFFULL
127 #define SCSI_TIMEOUT_MS 30000   // 30 second timeout; currently no method to override
128 #define MAX_SB 64               // sense block maximum return size
129 /*
130 #define FIO_SGIO_DEBUG
131 */
132
133 struct sgio_cmd {
134         unsigned char cdb[16];      // enhanced from 10 to support 16 byte commands
135         unsigned char sb[MAX_SB];   // add sense block to commands
136         int nr;
137 };
138
139 struct sgio_trim {
140         char *unmap_param;
141         unsigned int unmap_range_count;
142         struct io_u **trim_io_us;
143 };
144
145 struct sgio_data {
146         struct sgio_cmd *cmds;
147         struct io_u **events;
148         struct pollfd *pfds;
149         int *fd_flags;
150         void *sgbuf;
151         unsigned int bs;
152         int type_checked;
153         struct sgio_trim **trim_queues;
154         int current_queue;
155 #ifdef FIO_SGIO_DEBUG
156         unsigned int *trim_queue_map;
157 #endif
158 };
159
160 static inline bool sgio_unbuffered(struct thread_data *td)
161 {
162         return (td->o.odirect || td->o.sync_io);
163 }
164
165 static void sgio_hdr_init(struct sgio_data *sd, struct sg_io_hdr *hdr,
166                           struct io_u *io_u, int fs)
167 {
168         struct sgio_cmd *sc = &sd->cmds[io_u->index];
169
170         memset(hdr, 0, sizeof(*hdr));
171         memset(sc->cdb, 0, sizeof(sc->cdb));
172
173         hdr->interface_id = 'S';
174         hdr->cmdp = sc->cdb;
175         hdr->cmd_len = sizeof(sc->cdb);
176         hdr->sbp = sc->sb;
177         hdr->mx_sb_len = sizeof(sc->sb);
178         hdr->pack_id = io_u->index;
179         hdr->usr_ptr = io_u;
180         hdr->timeout = SCSI_TIMEOUT_MS;
181
182         if (fs) {
183                 hdr->dxferp = io_u->xfer_buf;
184                 hdr->dxfer_len = io_u->xfer_buflen;
185         }
186 }
187
188 static int pollin_events(struct pollfd *pfds, int fds)
189 {
190         int i;
191
192         for (i = 0; i < fds; i++)
193                 if (pfds[i].revents & POLLIN)
194                         return 1;
195
196         return 0;
197 }
198
199 static int sg_fd_read(int fd, void *data, size_t size)
200 {
201         int err = 0;
202
203         while (size) {
204                 ssize_t ret;
205
206                 ret = read(fd, data, size);
207                 if (ret < 0) {
208                         if (errno == EAGAIN || errno == EINTR)
209                                 continue;
210                         err = errno;
211                         break;
212                 } else if (!ret)
213                         break;
214                 else {
215                         data += ret;
216                         size -= ret;
217                 }
218         }
219
220         if (err)
221                 return err;
222         if (size)
223                 return EAGAIN;
224
225         return 0;
226 }
227
228 static int fio_sgio_getevents(struct thread_data *td, unsigned int min,
229                               unsigned int max,
230                               const struct timespec fio_unused *t)
231 {
232         struct sgio_data *sd = td->io_ops_data;
233         int left = max, eventNum, ret, r = 0, trims = 0;
234         void *buf = sd->sgbuf;
235         unsigned int i, j, events;
236         struct fio_file *f;
237         struct io_u *io_u;
238
239         /*
240          * Fill in the file descriptors
241          */
242         for_each_file(td, f, i) {
243                 /*
244                  * don't block for min events == 0
245                  */
246                 if (!min)
247                         sd->fd_flags[i] = fio_set_fd_nonblocking(f->fd, "sg");
248                 else
249                         sd->fd_flags[i] = -1;
250
251                 sd->pfds[i].fd = f->fd;
252                 sd->pfds[i].events = POLLIN;
253         }
254
255         /*
256         ** There are two counters here:
257         **  - number of SCSI commands completed
258         **  - number of io_us completed
259         **
260         ** These are the same with reads and writes, but
261         ** could differ with trim/unmap commands because
262         ** a single unmap can include multiple io_us
263         */
264
265         while (left > 0) {
266                 char *p;
267
268                 dprint(FD_IO, "sgio_getevents: sd %p: min=%d, max=%d, left=%d\n", sd, min, max, left);
269
270                 do {
271                         if (!min)
272                                 break;
273
274                         ret = poll(sd->pfds, td->o.nr_files, -1);
275                         if (ret < 0) {
276                                 if (!r)
277                                         r = -errno;
278                                 td_verror(td, errno, "poll");
279                                 break;
280                         } else if (!ret)
281                                 continue;
282
283                         if (pollin_events(sd->pfds, td->o.nr_files))
284                                 break;
285                 } while (1);
286
287                 if (r < 0)
288                         break;
289
290 re_read:
291                 p = buf;
292                 events = 0;
293                 for_each_file(td, f, i) {
294                         for (eventNum = 0; eventNum < left; eventNum++) {
295                                 ret = sg_fd_read(f->fd, p, sizeof(struct sg_io_hdr));
296                                 dprint(FD_IO, "sgio_getevents: sg_fd_read ret: %d\n", ret);
297                                 if (ret) {
298                                         r = -ret;
299                                         td_verror(td, r, "sg_read");
300                                         break;
301                                 }
302                                 io_u = ((struct sg_io_hdr *)p)->usr_ptr;
303                                 if (io_u->ddir == DDIR_TRIM) {
304                                         events += sd->trim_queues[io_u->index]->unmap_range_count;
305                                         eventNum += sd->trim_queues[io_u->index]->unmap_range_count - 1;
306                                 } else
307                                         events++;
308
309                                 p += sizeof(struct sg_io_hdr);
310                                 dprint(FD_IO, "sgio_getevents: events: %d, eventNum: %d, left: %d\n", events, eventNum, left);
311                         }
312                 }
313
314                 if (r < 0 && !events)
315                         break;
316                 if (!events) {
317                         usleep(1000);
318                         goto re_read;
319                 }
320
321                 left -= events;
322                 r += events;
323
324                 for (i = 0; i < events; i++) {
325                         struct sg_io_hdr *hdr = (struct sg_io_hdr *) buf + i;
326                         sd->events[i + trims] = hdr->usr_ptr;
327                         io_u = (struct io_u *)(hdr->usr_ptr);
328
329                         if (hdr->info & SG_INFO_CHECK) {
330                                 /* record if an io error occurred, ignore resid */
331                                 memcpy(&io_u->hdr, hdr, sizeof(struct sg_io_hdr));
332                                 sd->events[i + trims]->error = EIO;
333                         }
334
335                         if (io_u->ddir == DDIR_TRIM) {
336                                 struct sgio_trim *st = sd->trim_queues[io_u->index];
337 #ifdef FIO_SGIO_DEBUG
338                                 assert(st->trim_io_us[0] == io_u);
339                                 assert(sd->trim_queue_map[io_u->index] == io_u->index);
340                                 dprint(FD_IO, "sgio_getevents: reaping %d io_us from trim queue %d\n", st->unmap_range_count, io_u->index);
341                                 dprint(FD_IO, "sgio_getevents: reaped io_u %d and stored in events[%d]\n", io_u->index, i+trims);
342 #endif
343                                 for (j = 1; j < st->unmap_range_count; j++) {
344                                         ++trims;
345                                         sd->events[i + trims] = st->trim_io_us[j];
346 #ifdef FIO_SGIO_DEBUG
347                                         dprint(FD_IO, "sgio_getevents: reaped io_u %d and stored in events[%d]\n", st->trim_io_us[j]->index, i+trims);
348                                         assert(sd->trim_queue_map[st->trim_io_us[j]->index] == io_u->index);
349 #endif
350                                         if (hdr->info & SG_INFO_CHECK) {
351                                                 /* record if an io error occurred, ignore resid */
352                                                 memcpy(&st->trim_io_us[j]->hdr, hdr, sizeof(struct sg_io_hdr));
353                                                 sd->events[i + trims]->error = EIO;
354                                         }
355                                 }
356                                 events -= st->unmap_range_count - 1;
357                                 st->unmap_range_count = 0;
358                         }
359                 }
360         }
361
362         if (!min) {
363                 for_each_file(td, f, i) {
364                         if (sd->fd_flags[i] == -1)
365                                 continue;
366
367                         if (fcntl(f->fd, F_SETFL, sd->fd_flags[i]) < 0)
368                                 log_err("fio: sg failed to restore fcntl flags: %s\n", strerror(errno));
369                 }
370         }
371
372         return r;
373 }
374
375 static enum fio_q_status fio_sgio_ioctl_doio(struct thread_data *td,
376                                              struct fio_file *f,
377                                              struct io_u *io_u)
378 {
379         struct sgio_data *sd = td->io_ops_data;
380         struct sg_io_hdr *hdr = &io_u->hdr;
381         int ret;
382
383         sd->events[0] = io_u;
384
385         ret = ioctl(f->fd, SG_IO, hdr);
386         if (ret < 0)
387                 return ret;
388
389         /* record if an io error occurred */
390         if (hdr->info & SG_INFO_CHECK)
391                 io_u->error = EIO;
392
393         return FIO_Q_COMPLETED;
394 }
395
396 static enum fio_q_status fio_sgio_rw_doio(struct fio_file *f,
397                                           struct io_u *io_u, int do_sync)
398 {
399         struct sg_io_hdr *hdr = &io_u->hdr;
400         int ret;
401
402         ret = write(f->fd, hdr, sizeof(*hdr));
403         if (ret < 0)
404                 return ret;
405
406         if (do_sync) {
407                 ret = read(f->fd, hdr, sizeof(*hdr));
408                 if (ret < 0)
409                         return ret;
410
411                 /* record if an io error occurred */
412                 if (hdr->info & SG_INFO_CHECK)
413                         io_u->error = EIO;
414
415                 return FIO_Q_COMPLETED;
416         }
417
418         return FIO_Q_QUEUED;
419 }
420
421 static enum fio_q_status fio_sgio_doio(struct thread_data *td,
422                                        struct io_u *io_u, int do_sync)
423 {
424         struct fio_file *f = io_u->file;
425         enum fio_q_status ret;
426
427         if (f->filetype == FIO_TYPE_BLOCK) {
428                 ret = fio_sgio_ioctl_doio(td, f, io_u);
429                 td_verror(td, io_u->error, __func__);
430         } else {
431                 ret = fio_sgio_rw_doio(f, io_u, do_sync);
432                 if (do_sync)
433                         td_verror(td, io_u->error, __func__);
434         }
435
436         return ret;
437 }
438
439 static void fio_sgio_rw_lba(struct sg_io_hdr *hdr, unsigned long long lba,
440                             unsigned long long nr_blocks)
441 {
442         if (lba < MAX_10B_LBA) {
443                 hdr->cmdp[2] = (unsigned char) ((lba >> 24) & 0xff);
444                 hdr->cmdp[3] = (unsigned char) ((lba >> 16) & 0xff);
445                 hdr->cmdp[4] = (unsigned char) ((lba >>  8) & 0xff);
446                 hdr->cmdp[5] = (unsigned char) (lba & 0xff);
447                 hdr->cmdp[7] = (unsigned char) ((nr_blocks >> 8) & 0xff);
448                 hdr->cmdp[8] = (unsigned char) (nr_blocks & 0xff);
449         } else {
450                 hdr->cmdp[2] = (unsigned char) ((lba >> 56) & 0xff);
451                 hdr->cmdp[3] = (unsigned char) ((lba >> 48) & 0xff);
452                 hdr->cmdp[4] = (unsigned char) ((lba >> 40) & 0xff);
453                 hdr->cmdp[5] = (unsigned char) ((lba >> 32) & 0xff);
454                 hdr->cmdp[6] = (unsigned char) ((lba >> 24) & 0xff);
455                 hdr->cmdp[7] = (unsigned char) ((lba >> 16) & 0xff);
456                 hdr->cmdp[8] = (unsigned char) ((lba >>  8) & 0xff);
457                 hdr->cmdp[9] = (unsigned char) (lba & 0xff);
458                 hdr->cmdp[10] = (unsigned char) ((nr_blocks >> 32) & 0xff);
459                 hdr->cmdp[11] = (unsigned char) ((nr_blocks >> 16) & 0xff);
460                 hdr->cmdp[12] = (unsigned char) ((nr_blocks >> 8) & 0xff);
461                 hdr->cmdp[13] = (unsigned char) (nr_blocks & 0xff);
462         }
463
464         return;
465 }
466
467 static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
468 {
469         struct sg_io_hdr *hdr = &io_u->hdr;
470         struct sg_options *o = td->eo;
471         struct sgio_data *sd = td->io_ops_data;
472         unsigned long long nr_blocks, lba;
473         int offset;
474
475         if (io_u->xfer_buflen & (sd->bs - 1)) {
476                 log_err("read/write not sector aligned\n");
477                 return EINVAL;
478         }
479
480         nr_blocks = io_u->xfer_buflen / sd->bs;
481         lba = io_u->offset / sd->bs;
482
483         if (io_u->ddir == DDIR_READ) {
484                 sgio_hdr_init(sd, hdr, io_u, 1);
485
486                 hdr->dxfer_direction = SG_DXFER_FROM_DEV;
487                 if (lba < MAX_10B_LBA)
488                         hdr->cmdp[0] = 0x28; // read(10)
489                 else
490                         hdr->cmdp[0] = 0x88; // read(16)
491
492                 if (o->readfua)
493                         hdr->cmdp[1] |= 0x08;
494
495                 fio_sgio_rw_lba(hdr, lba, nr_blocks);
496
497         } else if (io_u->ddir == DDIR_WRITE) {
498                 sgio_hdr_init(sd, hdr, io_u, 1);
499
500                 hdr->dxfer_direction = SG_DXFER_TO_DEV;
501                 switch(o->write_mode) {
502                 case FIO_SG_WRITE:
503                         if (lba < MAX_10B_LBA)
504                                 hdr->cmdp[0] = 0x2a; // write(10)
505                         else
506                                 hdr->cmdp[0] = 0x8a; // write(16)
507                         if (o->writefua)
508                                 hdr->cmdp[1] |= 0x08;
509                         break;
510                 case FIO_SG_WRITE_VERIFY:
511                         if (lba < MAX_10B_LBA)
512                                 hdr->cmdp[0] = 0x2e; // write and verify(10)
513                         else
514                                 hdr->cmdp[0] = 0x8e; // write and verify(16)
515                         break;
516                         // BYTCHK is disabled by virtue of the memset in sgio_hdr_init
517                 case FIO_SG_WRITE_SAME:
518                         hdr->dxfer_len = sd->bs;
519                         if (lba < MAX_10B_LBA)
520                                 hdr->cmdp[0] = 0x41; // write same(10)
521                         else
522                                 hdr->cmdp[0] = 0x93; // write same(16)
523                         break;
524                 };
525
526                 fio_sgio_rw_lba(hdr, lba, nr_blocks);
527
528         } else if (io_u->ddir == DDIR_TRIM) {
529                 struct sgio_trim *st;
530
531                 if (sd->current_queue == -1) {
532                         sgio_hdr_init(sd, hdr, io_u, 0);
533
534                         hdr->cmd_len = 10;
535                         hdr->dxfer_direction = SG_DXFER_TO_DEV;
536                         hdr->cmdp[0] = 0x42; // unmap
537                         sd->current_queue = io_u->index;
538                         st = sd->trim_queues[sd->current_queue];
539                         hdr->dxferp = st->unmap_param;
540 #ifdef FIO_SGIO_DEBUG
541                         assert(sd->trim_queues[io_u->index]->unmap_range_count == 0);
542                         dprint(FD_IO, "sg: creating new queue based on io_u %d\n", io_u->index);
543 #endif
544                 }
545                 else
546                         st = sd->trim_queues[sd->current_queue];
547
548                 dprint(FD_IO, "sg: adding io_u %d to trim queue %d\n", io_u->index, sd->current_queue);
549                 st->trim_io_us[st->unmap_range_count] = io_u;
550 #ifdef FIO_SGIO_DEBUG
551                 sd->trim_queue_map[io_u->index] = sd->current_queue;
552 #endif
553
554                 offset = 8 + 16 * st->unmap_range_count;
555                 st->unmap_param[offset] = (unsigned char) ((lba >> 56) & 0xff);
556                 st->unmap_param[offset+1] = (unsigned char) ((lba >> 48) & 0xff);
557                 st->unmap_param[offset+2] = (unsigned char) ((lba >> 40) & 0xff);
558                 st->unmap_param[offset+3] = (unsigned char) ((lba >> 32) & 0xff);
559                 st->unmap_param[offset+4] = (unsigned char) ((lba >> 24) & 0xff);
560                 st->unmap_param[offset+5] = (unsigned char) ((lba >> 16) & 0xff);
561                 st->unmap_param[offset+6] = (unsigned char) ((lba >>  8) & 0xff);
562                 st->unmap_param[offset+7] = (unsigned char) (lba & 0xff);
563                 st->unmap_param[offset+8] = (unsigned char) ((nr_blocks >> 32) & 0xff);
564                 st->unmap_param[offset+9] = (unsigned char) ((nr_blocks >> 16) & 0xff);
565                 st->unmap_param[offset+10] = (unsigned char) ((nr_blocks >> 8) & 0xff);
566                 st->unmap_param[offset+11] = (unsigned char) (nr_blocks & 0xff);
567
568                 st->unmap_range_count++;
569
570         } else if (ddir_sync(io_u->ddir)) {
571                 sgio_hdr_init(sd, hdr, io_u, 0);
572                 hdr->dxfer_direction = SG_DXFER_NONE;
573                 if (lba < MAX_10B_LBA)
574                         hdr->cmdp[0] = 0x35; // synccache(10)
575                 else
576                         hdr->cmdp[0] = 0x91; // synccache(16)
577         } else
578                 assert(0);
579
580         return 0;
581 }
582
583 static void fio_sgio_unmap_setup(struct sg_io_hdr *hdr, struct sgio_trim *st)
584 {
585         hdr->dxfer_len = st->unmap_range_count * 16 + 8;
586         hdr->cmdp[7] = (unsigned char) (((st->unmap_range_count * 16 + 8) >> 8) & 0xff);
587         hdr->cmdp[8] = (unsigned char) ((st->unmap_range_count * 16 + 8) & 0xff);
588
589         st->unmap_param[0] = (unsigned char) (((16 * st->unmap_range_count + 6) >> 8) & 0xff);
590         st->unmap_param[1] = (unsigned char)  ((16 * st->unmap_range_count + 6) & 0xff);
591         st->unmap_param[2] = (unsigned char) (((16 * st->unmap_range_count) >> 8) & 0xff);
592         st->unmap_param[3] = (unsigned char)  ((16 * st->unmap_range_count) & 0xff);
593
594         return;
595 }
596
597 static enum fio_q_status fio_sgio_queue(struct thread_data *td,
598                                         struct io_u *io_u)
599 {
600         struct sg_io_hdr *hdr = &io_u->hdr;
601         struct sgio_data *sd = td->io_ops_data;
602         int ret, do_sync = 0;
603
604         fio_ro_check(td, io_u);
605
606         if (sgio_unbuffered(td) || ddir_sync(io_u->ddir))
607                 do_sync = 1;
608
609         if (io_u->ddir == DDIR_TRIM) {
610                 if (do_sync || io_u->file->filetype == FIO_TYPE_BLOCK) {
611                         struct sgio_trim *st = sd->trim_queues[sd->current_queue];
612
613                         /* finish cdb setup for unmap because we are
614                         ** doing unmap commands synchronously */
615 #ifdef FIO_SGIO_DEBUG
616                         assert(st->unmap_range_count == 1);
617                         assert(io_u == st->trim_io_us[0]);
618 #endif
619                         hdr = &io_u->hdr;
620
621                         fio_sgio_unmap_setup(hdr, st);
622
623                         st->unmap_range_count = 0;
624                         sd->current_queue = -1;
625                 } else
626                         /* queue up trim ranges and submit in commit() */
627                         return FIO_Q_QUEUED;
628         }
629
630         ret = fio_sgio_doio(td, io_u, do_sync);
631
632         if (ret < 0)
633                 io_u->error = errno;
634         else if (hdr->status) {
635                 io_u->resid = hdr->resid;
636                 io_u->error = EIO;
637         } else if (td->io_ops->commit != NULL) {
638                 if (do_sync && !ddir_sync(io_u->ddir)) {
639                         io_u_mark_submit(td, 1);
640                         io_u_mark_complete(td, 1);
641                 } else if (io_u->ddir == DDIR_READ || io_u->ddir == DDIR_WRITE) {
642                         io_u_mark_submit(td, 1);
643                         io_u_queued(td, io_u);
644                 }
645         }
646
647         if (io_u->error) {
648                 td_verror(td, io_u->error, "xfer");
649                 return FIO_Q_COMPLETED;
650         }
651
652         return ret;
653 }
654
655 static int fio_sgio_commit(struct thread_data *td)
656 {
657         struct sgio_data *sd = td->io_ops_data;
658         struct sgio_trim *st;
659         struct io_u *io_u;
660         struct sg_io_hdr *hdr;
661         struct timespec now;
662         unsigned int i;
663         int ret;
664
665         if (sd->current_queue == -1)
666                 return 0;
667
668         st = sd->trim_queues[sd->current_queue];
669         io_u = st->trim_io_us[0];
670         hdr = &io_u->hdr;
671
672         fio_sgio_unmap_setup(hdr, st);
673
674         sd->current_queue = -1;
675
676         ret = fio_sgio_rw_doio(io_u->file, io_u, 0);
677
678         if (ret < 0 || hdr->status) {
679                 int error;
680
681                 if (ret < 0)
682                         error = errno;
683                 else {
684                         error = EIO;
685                         ret = -EIO;
686                 }
687
688                 for (i = 0; i < st->unmap_range_count; i++) {
689                         st->trim_io_us[i]->error = error;
690                         clear_io_u(td, st->trim_io_us[i]);
691                         if (hdr->status)
692                                 st->trim_io_us[i]->resid = hdr->resid;
693                 }
694
695                 td_verror(td, error, "xfer");
696                 return ret;
697         }
698
699         if (fio_fill_issue_time(td)) {
700                 fio_gettime(&now, NULL);
701                 for (i = 0; i < st->unmap_range_count; i++) {
702                         memcpy(&st->trim_io_us[i]->issue_time, &now, sizeof(now));
703                         io_u_queued(td, io_u);
704                 }
705         }
706         io_u_mark_submit(td, st->unmap_range_count);
707
708         return 0;
709 }
710
711 static struct io_u *fio_sgio_event(struct thread_data *td, int event)
712 {
713         struct sgio_data *sd = td->io_ops_data;
714
715         return sd->events[event];
716 }
717
718 static int fio_sgio_read_capacity(struct thread_data *td, unsigned int *bs,
719                                   unsigned long long *max_lba)
720 {
721         /*
722          * need to do read capacity operation w/o benefit of sd or
723          * io_u structures, which are not initialized until later.
724          */
725         struct sg_io_hdr hdr;
726         unsigned long long hlba;
727         unsigned int blksz = 0;
728         unsigned char cmd[16];
729         unsigned char sb[64];
730         unsigned char buf[32];  // read capacity return
731         int ret;
732         int fd = -1;
733
734         struct fio_file *f = td->files[0];
735
736         /* open file independent of rest of application */
737         fd = open(f->file_name, O_RDONLY);
738         if (fd < 0)
739                 return -errno;
740
741         memset(&hdr, 0, sizeof(hdr));
742         memset(cmd, 0, sizeof(cmd));
743         memset(sb, 0, sizeof(sb));
744         memset(buf, 0, sizeof(buf));
745
746         /* First let's try a 10 byte read capacity. */
747         hdr.interface_id = 'S';
748         hdr.cmdp = cmd;
749         hdr.cmd_len = 10;
750         hdr.sbp = sb;
751         hdr.mx_sb_len = sizeof(sb);
752         hdr.timeout = SCSI_TIMEOUT_MS;
753         hdr.cmdp[0] = 0x25;  // Read Capacity(10)
754         hdr.dxfer_direction = SG_DXFER_FROM_DEV;
755         hdr.dxferp = buf;
756         hdr.dxfer_len = sizeof(buf);
757
758         ret = ioctl(fd, SG_IO, &hdr);
759         if (ret < 0) {
760                 close(fd);
761                 return ret;
762         }
763
764         if (hdr.info & SG_INFO_CHECK) {
765                 /* RCAP(10) might be unsupported by device. Force RCAP(16) */
766                 hlba = MAX_10B_LBA;
767         } else {
768                 blksz    = ((unsigned long) buf[4] << 24) | ((unsigned long) buf[5] << 16) |
769                            ((unsigned long) buf[6] << 8) | (unsigned long) buf[7];
770                 hlba     = ((unsigned long) buf[0] << 24) | ((unsigned long) buf[1] << 16) |
771                            ((unsigned long) buf[2] << 8) | (unsigned long) buf[3];
772         }
773
774         /*
775          * If max lba masked by MAX_10B_LBA equals MAX_10B_LBA,
776          * then need to retry with 16 byte Read Capacity command.
777          */
778         if (hlba == MAX_10B_LBA) {
779                 hdr.cmd_len = 16;
780                 hdr.cmdp[0] = 0x9e; // service action
781                 hdr.cmdp[1] = 0x10; // Read Capacity(16)
782                 hdr.cmdp[10] = (unsigned char) ((sizeof(buf) >> 24) & 0xff);
783                 hdr.cmdp[11] = (unsigned char) ((sizeof(buf) >> 16) & 0xff);
784                 hdr.cmdp[12] = (unsigned char) ((sizeof(buf) >> 8) & 0xff);
785                 hdr.cmdp[13] = (unsigned char) (sizeof(buf) & 0xff);
786
787                 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
788                 hdr.dxferp = buf;
789                 hdr.dxfer_len = sizeof(buf);
790
791                 ret = ioctl(fd, SG_IO, &hdr);
792                 if (ret < 0) {
793                         close(fd);
794                         return ret;
795                 }
796
797                 /* record if an io error occurred */
798                 if (hdr.info & SG_INFO_CHECK)
799                         td_verror(td, EIO, "fio_sgio_read_capacity");
800
801                 blksz = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
802                 hlba  = ((unsigned long long)buf[0] << 56) |
803                         ((unsigned long long)buf[1] << 48) |
804                         ((unsigned long long)buf[2] << 40) |
805                         ((unsigned long long)buf[3] << 32) |
806                         ((unsigned long long)buf[4] << 24) |
807                         ((unsigned long long)buf[5] << 16) |
808                         ((unsigned long long)buf[6] << 8) |
809                         (unsigned long long)buf[7];
810         }
811
812         if (blksz) {
813                 *bs = blksz;
814                 *max_lba = hlba;
815                 ret = 0;
816         } else {
817                 ret = EIO;
818         }
819
820         close(fd);
821         return ret;
822 }
823
824 static void fio_sgio_cleanup(struct thread_data *td)
825 {
826         struct sgio_data *sd = td->io_ops_data;
827         int i;
828
829         if (sd) {
830                 free(sd->events);
831                 free(sd->cmds);
832                 free(sd->fd_flags);
833                 free(sd->pfds);
834                 free(sd->sgbuf);
835 #ifdef FIO_SGIO_DEBUG
836                 free(sd->trim_queue_map);
837 #endif
838
839                 for (i = 0; i < td->o.iodepth; i++) {
840                         free(sd->trim_queues[i]->unmap_param);
841                         free(sd->trim_queues[i]->trim_io_us);
842                         free(sd->trim_queues[i]);
843                 }
844
845                 free(sd->trim_queues);
846                 free(sd);
847         }
848 }
849
850 static int fio_sgio_init(struct thread_data *td)
851 {
852         struct sgio_data *sd;
853         struct sgio_trim *st;
854         int i;
855
856         sd = calloc(1, sizeof(*sd));
857         sd->cmds = calloc(td->o.iodepth, sizeof(struct sgio_cmd));
858         sd->sgbuf = calloc(td->o.iodepth, sizeof(struct sg_io_hdr));
859         sd->events = calloc(td->o.iodepth, sizeof(struct io_u *));
860         sd->pfds = calloc(td->o.nr_files, sizeof(struct pollfd));
861         sd->fd_flags = calloc(td->o.nr_files, sizeof(int));
862         sd->type_checked = 0;
863
864         sd->trim_queues = calloc(td->o.iodepth, sizeof(struct sgio_trim *));
865         sd->current_queue = -1;
866 #ifdef FIO_SGIO_DEBUG
867         sd->trim_queue_map = calloc(td->o.iodepth, sizeof(int));
868 #endif
869         for (i = 0; i < td->o.iodepth; i++) {
870                 sd->trim_queues[i] = calloc(1, sizeof(struct sgio_trim));
871                 st = sd->trim_queues[i];
872                 st->unmap_param = calloc(td->o.iodepth + 1, sizeof(char[16]));
873                 st->unmap_range_count = 0;
874                 st->trim_io_us = calloc(td->o.iodepth, sizeof(struct io_u *));
875         }
876
877         td->io_ops_data = sd;
878
879         /*
880          * we want to do it, regardless of whether odirect is set or not
881          */
882         td->o.override_sync = 1;
883         return 0;
884 }
885
886 static int fio_sgio_type_check(struct thread_data *td, struct fio_file *f)
887 {
888         struct sgio_data *sd = td->io_ops_data;
889         unsigned int bs = 0;
890         unsigned long long max_lba = 0;
891
892         if (f->filetype == FIO_TYPE_BLOCK) {
893                 if (ioctl(f->fd, BLKSSZGET, &bs) < 0) {
894                         td_verror(td, errno, "ioctl");
895                         return 1;
896                 }
897         } else if (f->filetype == FIO_TYPE_CHAR) {
898                 int version, ret;
899
900                 if (ioctl(f->fd, SG_GET_VERSION_NUM, &version) < 0) {
901                         td_verror(td, errno, "ioctl");
902                         return 1;
903                 }
904
905                 ret = fio_sgio_read_capacity(td, &bs, &max_lba);
906                 if (ret) {
907                         td_verror(td, td->error, "fio_sgio_read_capacity");
908                         log_err("ioengine sg unable to read capacity successfully\n");
909                         return 1;
910                 }
911         } else {
912                 td_verror(td, EINVAL, "wrong file type");
913                 log_err("ioengine sg only works on block or character devices\n");
914                 return 1;
915         }
916
917         sd->bs = bs;
918         // Determine size of commands needed based on max_lba
919         if (max_lba >= MAX_10B_LBA) {
920                 dprint(FD_IO, "sgio_type_check: using 16 byte read/write "
921                         "commands for lba above 0x%016llx/0x%016llx\n",
922                         MAX_10B_LBA, max_lba);
923         }
924
925         if (f->filetype == FIO_TYPE_BLOCK) {
926                 td->io_ops->getevents = NULL;
927                 td->io_ops->event = NULL;
928                 td->io_ops->commit = NULL;
929                 /*
930                 ** Setting these functions to null may cause problems
931                 ** with filename=/dev/sda:/dev/sg0 since we are only
932                 ** considering a single file
933                 */
934         }
935         sd->type_checked = 1;
936
937         return 0;
938 }
939
940 static int fio_sgio_open(struct thread_data *td, struct fio_file *f)
941 {
942         struct sgio_data *sd = td->io_ops_data;
943         int ret;
944
945         ret = generic_open_file(td, f);
946         if (ret)
947                 return ret;
948
949         if (sd && !sd->type_checked && fio_sgio_type_check(td, f)) {
950                 ret = generic_close_file(td, f);
951                 return 1;
952         }
953
954         return 0;
955 }
956
957 /*
958  * Build an error string with details about the driver, host or scsi
959  * error contained in the sg header Caller will use as necessary.
960  */
961 static char *fio_sgio_errdetails(struct io_u *io_u)
962 {
963         struct sg_io_hdr *hdr = &io_u->hdr;
964 #define MAXERRDETAIL 1024
965 #define MAXMSGCHUNK  128
966         char *msg, msgchunk[MAXMSGCHUNK];
967         int i;
968
969         msg = calloc(1, MAXERRDETAIL);
970         strcpy(msg, "");
971
972         /*
973          * can't seem to find sg_err.h, so I'll just echo the define values
974          * so others can search on internet to find clearer clues of meaning.
975          */
976         if (hdr->info & SG_INFO_CHECK) {
977                 if (hdr->host_status) {
978                         snprintf(msgchunk, MAXMSGCHUNK, "SG Host Status: 0x%02x; ", hdr->host_status);
979                         strlcat(msg, msgchunk, MAXERRDETAIL);
980                         switch (hdr->host_status) {
981                         case 0x01:
982                                 strlcat(msg, "SG_ERR_DID_NO_CONNECT", MAXERRDETAIL);
983                                 break;
984                         case 0x02:
985                                 strlcat(msg, "SG_ERR_DID_BUS_BUSY", MAXERRDETAIL);
986                                 break;
987                         case 0x03:
988                                 strlcat(msg, "SG_ERR_DID_TIME_OUT", MAXERRDETAIL);
989                                 break;
990                         case 0x04:
991                                 strlcat(msg, "SG_ERR_DID_BAD_TARGET", MAXERRDETAIL);
992                                 break;
993                         case 0x05:
994                                 strlcat(msg, "SG_ERR_DID_ABORT", MAXERRDETAIL);
995                                 break;
996                         case 0x06:
997                                 strlcat(msg, "SG_ERR_DID_PARITY", MAXERRDETAIL);
998                                 break;
999                         case 0x07:
1000                                 strlcat(msg, "SG_ERR_DID_ERROR (internal error)", MAXERRDETAIL);
1001                                 break;
1002                         case 0x08:
1003                                 strlcat(msg, "SG_ERR_DID_RESET", MAXERRDETAIL);
1004                                 break;
1005                         case 0x09:
1006                                 strlcat(msg, "SG_ERR_DID_BAD_INTR (unexpected)", MAXERRDETAIL);
1007                                 break;
1008                         case 0x0a:
1009                                 strlcat(msg, "SG_ERR_DID_PASSTHROUGH", MAXERRDETAIL);
1010                                 break;
1011                         case 0x0b:
1012                                 strlcat(msg, "SG_ERR_DID_SOFT_ERROR (driver retry?)", MAXERRDETAIL);
1013                                 break;
1014                         case 0x0c:
1015                                 strlcat(msg, "SG_ERR_DID_IMM_RETRY", MAXERRDETAIL);
1016                                 break;
1017                         case 0x0d:
1018                                 strlcat(msg, "SG_ERR_DID_REQUEUE", MAXERRDETAIL);
1019                                 break;
1020                         case 0x0e:
1021                                 strlcat(msg, "SG_ERR_DID_TRANSPORT_DISRUPTED", MAXERRDETAIL);
1022                                 break;
1023                         case 0x0f:
1024                                 strlcat(msg, "SG_ERR_DID_TRANSPORT_FAILFAST", MAXERRDETAIL);
1025                                 break;
1026                         case 0x10:
1027                                 strlcat(msg, "SG_ERR_DID_TARGET_FAILURE", MAXERRDETAIL);
1028                                 break;
1029                         case 0x11:
1030                                 strlcat(msg, "SG_ERR_DID_NEXUS_FAILURE", MAXERRDETAIL);
1031                                 break;
1032                         case 0x12:
1033                                 strlcat(msg, "SG_ERR_DID_ALLOC_FAILURE", MAXERRDETAIL);
1034                                 break;
1035                         case 0x13:
1036                                 strlcat(msg, "SG_ERR_DID_MEDIUM_ERROR", MAXERRDETAIL);
1037                                 break;
1038                         default:
1039                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1040                                 break;
1041                         }
1042                         strlcat(msg, ". ", MAXERRDETAIL);
1043                 }
1044                 if (hdr->driver_status) {
1045                         snprintf(msgchunk, MAXMSGCHUNK, "SG Driver Status: 0x%02x; ", hdr->driver_status);
1046                         strlcat(msg, msgchunk, MAXERRDETAIL);
1047                         switch (hdr->driver_status & 0x0F) {
1048                         case 0x01:
1049                                 strlcat(msg, "SG_ERR_DRIVER_BUSY", MAXERRDETAIL);
1050                                 break;
1051                         case 0x02:
1052                                 strlcat(msg, "SG_ERR_DRIVER_SOFT", MAXERRDETAIL);
1053                                 break;
1054                         case 0x03:
1055                                 strlcat(msg, "SG_ERR_DRIVER_MEDIA", MAXERRDETAIL);
1056                                 break;
1057                         case 0x04:
1058                                 strlcat(msg, "SG_ERR_DRIVER_ERROR", MAXERRDETAIL);
1059                                 break;
1060                         case 0x05:
1061                                 strlcat(msg, "SG_ERR_DRIVER_INVALID", MAXERRDETAIL);
1062                                 break;
1063                         case 0x06:
1064                                 strlcat(msg, "SG_ERR_DRIVER_TIMEOUT", MAXERRDETAIL);
1065                                 break;
1066                         case 0x07:
1067                                 strlcat(msg, "SG_ERR_DRIVER_HARD", MAXERRDETAIL);
1068                                 break;
1069                         case 0x08:
1070                                 strlcat(msg, "SG_ERR_DRIVER_SENSE", MAXERRDETAIL);
1071                                 break;
1072                         default:
1073                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1074                                 break;
1075                         }
1076                         strlcat(msg, "; ", MAXERRDETAIL);
1077                         switch (hdr->driver_status & 0xF0) {
1078                         case 0x10:
1079                                 strlcat(msg, "SG_ERR_SUGGEST_RETRY", MAXERRDETAIL);
1080                                 break;
1081                         case 0x20:
1082                                 strlcat(msg, "SG_ERR_SUGGEST_ABORT", MAXERRDETAIL);
1083                                 break;
1084                         case 0x30:
1085                                 strlcat(msg, "SG_ERR_SUGGEST_REMAP", MAXERRDETAIL);
1086                                 break;
1087                         case 0x40:
1088                                 strlcat(msg, "SG_ERR_SUGGEST_DIE", MAXERRDETAIL);
1089                                 break;
1090                         case 0x80:
1091                                 strlcat(msg, "SG_ERR_SUGGEST_SENSE", MAXERRDETAIL);
1092                                 break;
1093                         }
1094                         strlcat(msg, ". ", MAXERRDETAIL);
1095                 }
1096                 if (hdr->status) {
1097                         snprintf(msgchunk, MAXMSGCHUNK, "SG SCSI Status: 0x%02x; ", hdr->status);
1098                         strlcat(msg, msgchunk, MAXERRDETAIL);
1099                         // SCSI 3 status codes
1100                         switch (hdr->status) {
1101                         case 0x02:
1102                                 strlcat(msg, "CHECK_CONDITION", MAXERRDETAIL);
1103                                 break;
1104                         case 0x04:
1105                                 strlcat(msg, "CONDITION_MET", MAXERRDETAIL);
1106                                 break;
1107                         case 0x08:
1108                                 strlcat(msg, "BUSY", MAXERRDETAIL);
1109                                 break;
1110                         case 0x10:
1111                                 strlcat(msg, "INTERMEDIATE", MAXERRDETAIL);
1112                                 break;
1113                         case 0x14:
1114                                 strlcat(msg, "INTERMEDIATE_CONDITION_MET", MAXERRDETAIL);
1115                                 break;
1116                         case 0x18:
1117                                 strlcat(msg, "RESERVATION_CONFLICT", MAXERRDETAIL);
1118                                 break;
1119                         case 0x22:
1120                                 strlcat(msg, "COMMAND_TERMINATED", MAXERRDETAIL);
1121                                 break;
1122                         case 0x28:
1123                                 strlcat(msg, "TASK_SET_FULL", MAXERRDETAIL);
1124                                 break;
1125                         case 0x30:
1126                                 strlcat(msg, "ACA_ACTIVE", MAXERRDETAIL);
1127                                 break;
1128                         case 0x40:
1129                                 strlcat(msg, "TASK_ABORTED", MAXERRDETAIL);
1130                                 break;
1131                         default:
1132                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1133                                 break;
1134                         }
1135                         strlcat(msg, ". ", MAXERRDETAIL);
1136                 }
1137                 if (hdr->sb_len_wr) {
1138                         snprintf(msgchunk, MAXMSGCHUNK, "Sense Data (%d bytes):", hdr->sb_len_wr);
1139                         strlcat(msg, msgchunk, MAXERRDETAIL);
1140                         for (i = 0; i < hdr->sb_len_wr; i++) {
1141                                 snprintf(msgchunk, MAXMSGCHUNK, " %02x", hdr->sbp[i]);
1142                                 strlcat(msg, msgchunk, MAXERRDETAIL);
1143                         }
1144                         strlcat(msg, ". ", MAXERRDETAIL);
1145                 }
1146                 if (hdr->resid != 0) {
1147                         snprintf(msgchunk, MAXMSGCHUNK, "SG Driver: %d bytes out of %d not transferred. ", hdr->resid, hdr->dxfer_len);
1148                         strlcat(msg, msgchunk, MAXERRDETAIL);
1149                 }
1150                 if (hdr->cmdp) {
1151                         strlcat(msg, "cdb:", MAXERRDETAIL);
1152                         for (i = 0; i < hdr->cmd_len; i++) {
1153                                 snprintf(msgchunk, MAXMSGCHUNK, " %02x", hdr->cmdp[i]);
1154                                 strlcat(msg, msgchunk, MAXERRDETAIL);
1155                         }
1156                         strlcat(msg, ". ", MAXERRDETAIL);
1157                         if (io_u->ddir == DDIR_TRIM) {
1158                                 unsigned char *param_list = hdr->dxferp;
1159                                 strlcat(msg, "dxferp:", MAXERRDETAIL);
1160                                 for (i = 0; i < hdr->dxfer_len; i++) {
1161                                         snprintf(msgchunk, MAXMSGCHUNK, " %02x", param_list[i]);
1162                                         strlcat(msg, msgchunk, MAXERRDETAIL);
1163                                 }
1164                                 strlcat(msg, ". ", MAXERRDETAIL);
1165                         }
1166                 }
1167         }
1168
1169         if (!(hdr->info & SG_INFO_CHECK) && !strlen(msg))
1170                 strncpy(msg, "SG Driver did not report a Host, Driver or Device check",
1171                         MAXERRDETAIL - 1);
1172
1173         return msg;
1174 }
1175
1176 /*
1177  * get max file size from read capacity.
1178  */
1179 static int fio_sgio_get_file_size(struct thread_data *td, struct fio_file *f)
1180 {
1181         /*
1182          * get_file_size is being called even before sgio_init is
1183          * called, so none of the sg_io structures are
1184          * initialized in the thread_data yet.  So we need to do the
1185          * ReadCapacity without any of those helpers.  One of the effects
1186          * is that ReadCapacity may get called 4 times on each open:
1187          * readcap(10) followed by readcap(16) if needed - just to get
1188          * the file size after the init occurs - it will be called
1189          * again when "type_check" is called during structure
1190          * initialization I'm not sure how to prevent this little
1191          * inefficiency.
1192          */
1193         unsigned int bs = 0;
1194         unsigned long long max_lba = 0;
1195         int ret;
1196
1197         if (fio_file_size_known(f))
1198                 return 0;
1199
1200         if (f->filetype != FIO_TYPE_BLOCK && f->filetype != FIO_TYPE_CHAR) {
1201                 td_verror(td, EINVAL, "wrong file type");
1202                 log_err("ioengine sg only works on block or character devices\n");
1203                 return 1;
1204         }
1205
1206         ret = fio_sgio_read_capacity(td, &bs, &max_lba);
1207         if (ret ) {
1208                 td_verror(td, td->error, "fio_sgio_read_capacity");
1209                 log_err("ioengine sg unable to successfully execute read capacity to get block size and maximum lba\n");
1210                 return 1;
1211         }
1212
1213         f->real_file_size = (max_lba + 1) * bs;
1214         fio_file_set_size_known(f);
1215         return 0;
1216 }
1217
1218
1219 static struct ioengine_ops ioengine = {
1220         .name           = "sg",
1221         .version        = FIO_IOOPS_VERSION,
1222         .init           = fio_sgio_init,
1223         .prep           = fio_sgio_prep,
1224         .queue          = fio_sgio_queue,
1225         .commit         = fio_sgio_commit,
1226         .getevents      = fio_sgio_getevents,
1227         .errdetails     = fio_sgio_errdetails,
1228         .event          = fio_sgio_event,
1229         .cleanup        = fio_sgio_cleanup,
1230         .open_file      = fio_sgio_open,
1231         .close_file     = generic_close_file,
1232         .get_file_size  = fio_sgio_get_file_size,
1233         .flags          = FIO_SYNCIO | FIO_RAWIO,
1234         .options        = options,
1235         .option_struct_size     = sizeof(struct sg_options)
1236 };
1237
1238 #else /* FIO_HAVE_SGIO */
1239
1240 /*
1241  * When we have a proper configure system in place, we simply wont build
1242  * and install this io engine. For now install a crippled version that
1243  * just complains and fails to load.
1244  */
1245 static int fio_sgio_init(struct thread_data fio_unused *td)
1246 {
1247         log_err("fio: ioengine sg not available\n");
1248         return 1;
1249 }
1250
1251 static struct ioengine_ops ioengine = {
1252         .name           = "sg",
1253         .version        = FIO_IOOPS_VERSION,
1254         .init           = fio_sgio_init,
1255 };
1256
1257 #endif
1258
1259 static void fio_init fio_sgio_register(void)
1260 {
1261         register_ioengine(&ioengine);
1262 }
1263
1264 static void fio_exit fio_sgio_unregister(void)
1265 {
1266         unregister_ioengine(&ioengine);
1267 }