Merge branch 'chunked-iolog-reading' of https://github.com/aclamk/fio
[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)
679                 for (i = 0; i < st->unmap_range_count; i++)
680                         st->trim_io_us[i]->error = errno;
681         else if (hdr->status)
682                 for (i = 0; i < st->unmap_range_count; i++) {
683                         st->trim_io_us[i]->resid = hdr->resid;
684                         st->trim_io_us[i]->error = EIO;
685                 }
686         else {
687                 if (fio_fill_issue_time(td)) {
688                         fio_gettime(&now, NULL);
689                         for (i = 0; i < st->unmap_range_count; i++) {
690                                 struct io_u *io_u = st->trim_io_us[i];
691
692                                 memcpy(&io_u->issue_time, &now, sizeof(now));
693                                 io_u_queued(td, io_u);
694                         }
695                 }
696                 io_u_mark_submit(td, st->unmap_range_count);
697         }
698
699         if (io_u->error) {
700                 td_verror(td, io_u->error, "xfer");
701                 return 0;
702         }
703
704         if (ret == FIO_Q_QUEUED)
705                 return 0;
706         else
707                 return ret;
708 }
709
710 static struct io_u *fio_sgio_event(struct thread_data *td, int event)
711 {
712         struct sgio_data *sd = td->io_ops_data;
713
714         return sd->events[event];
715 }
716
717 static int fio_sgio_read_capacity(struct thread_data *td, unsigned int *bs,
718                                   unsigned long long *max_lba)
719 {
720         /*
721          * need to do read capacity operation w/o benefit of sd or
722          * io_u structures, which are not initialized until later.
723          */
724         struct sg_io_hdr hdr;
725         unsigned char cmd[16];
726         unsigned char sb[64];
727         unsigned char buf[32];  // read capacity return
728         int ret;
729         int fd = -1;
730
731         struct fio_file *f = td->files[0];
732
733         /* open file independent of rest of application */
734         fd = open(f->file_name, O_RDONLY);
735         if (fd < 0)
736                 return -errno;
737
738         memset(&hdr, 0, sizeof(hdr));
739         memset(cmd, 0, sizeof(cmd));
740         memset(sb, 0, sizeof(sb));
741         memset(buf, 0, sizeof(buf));
742
743         /* First let's try a 10 byte read capacity. */
744         hdr.interface_id = 'S';
745         hdr.cmdp = cmd;
746         hdr.cmd_len = 10;
747         hdr.sbp = sb;
748         hdr.mx_sb_len = sizeof(sb);
749         hdr.timeout = SCSI_TIMEOUT_MS;
750         hdr.cmdp[0] = 0x25;  // Read Capacity(10)
751         hdr.dxfer_direction = SG_DXFER_FROM_DEV;
752         hdr.dxferp = buf;
753         hdr.dxfer_len = sizeof(buf);
754
755         ret = ioctl(fd, SG_IO, &hdr);
756         if (ret < 0) {
757                 close(fd);
758                 return ret;
759         }
760
761         *bs      = ((unsigned long) buf[4] << 24) | ((unsigned long) buf[5] << 16) |
762                    ((unsigned long) buf[6] << 8) | (unsigned long) buf[7];
763         *max_lba = ((unsigned long) buf[0] << 24) | ((unsigned long) buf[1] << 16) |
764                    ((unsigned long) buf[2] << 8) | (unsigned long) buf[3];
765
766         /*
767          * If max lba masked by MAX_10B_LBA equals MAX_10B_LBA,
768          * then need to retry with 16 byte Read Capacity command.
769          */
770         if (*max_lba == MAX_10B_LBA) {
771                 hdr.cmd_len = 16;
772                 hdr.cmdp[0] = 0x9e; // service action
773                 hdr.cmdp[1] = 0x10; // Read Capacity(16)
774                 hdr.cmdp[10] = (unsigned char) ((sizeof(buf) >> 24) & 0xff);
775                 hdr.cmdp[11] = (unsigned char) ((sizeof(buf) >> 16) & 0xff);
776                 hdr.cmdp[12] = (unsigned char) ((sizeof(buf) >> 8) & 0xff);
777                 hdr.cmdp[13] = (unsigned char) (sizeof(buf) & 0xff);
778
779                 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
780                 hdr.dxferp = buf;
781                 hdr.dxfer_len = sizeof(buf);
782
783                 ret = ioctl(fd, SG_IO, &hdr);
784                 if (ret < 0) {
785                         close(fd);
786                         return ret;
787                 }
788
789                 /* record if an io error occurred */
790                 if (hdr.info & SG_INFO_CHECK)
791                         td_verror(td, EIO, "fio_sgio_read_capacity");
792
793                 *bs = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
794                 *max_lba = ((unsigned long long)buf[0] << 56) |
795                                 ((unsigned long long)buf[1] << 48) |
796                                 ((unsigned long long)buf[2] << 40) |
797                                 ((unsigned long long)buf[3] << 32) |
798                                 ((unsigned long long)buf[4] << 24) |
799                                 ((unsigned long long)buf[5] << 16) |
800                                 ((unsigned long long)buf[6] << 8) |
801                                 (unsigned long long)buf[7];
802         }
803
804         close(fd);
805         return 0;
806 }
807
808 static void fio_sgio_cleanup(struct thread_data *td)
809 {
810         struct sgio_data *sd = td->io_ops_data;
811         int i;
812
813         if (sd) {
814                 free(sd->events);
815                 free(sd->cmds);
816                 free(sd->fd_flags);
817                 free(sd->pfds);
818                 free(sd->sgbuf);
819 #ifdef FIO_SGIO_DEBUG
820                 free(sd->trim_queue_map);
821 #endif
822
823                 for (i = 0; i < td->o.iodepth; i++) {
824                         free(sd->trim_queues[i]->unmap_param);
825                         free(sd->trim_queues[i]->trim_io_us);
826                         free(sd->trim_queues[i]);
827                 }
828
829                 free(sd->trim_queues);
830                 free(sd);
831         }
832 }
833
834 static int fio_sgio_init(struct thread_data *td)
835 {
836         struct sgio_data *sd;
837         struct sgio_trim *st;
838         int i;
839
840         sd = calloc(1, sizeof(*sd));
841         sd->cmds = calloc(td->o.iodepth, sizeof(struct sgio_cmd));
842         sd->sgbuf = calloc(td->o.iodepth, sizeof(struct sg_io_hdr));
843         sd->events = calloc(td->o.iodepth, sizeof(struct io_u *));
844         sd->pfds = calloc(td->o.nr_files, sizeof(struct pollfd));
845         sd->fd_flags = calloc(td->o.nr_files, sizeof(int));
846         sd->type_checked = 0;
847
848         sd->trim_queues = calloc(td->o.iodepth, sizeof(struct sgio_trim *));
849         sd->current_queue = -1;
850 #ifdef FIO_SGIO_DEBUG
851         sd->trim_queue_map = calloc(td->o.iodepth, sizeof(int));
852 #endif
853         for (i = 0; i < td->o.iodepth; i++) {
854                 sd->trim_queues[i] = calloc(1, sizeof(struct sgio_trim));
855                 st = sd->trim_queues[i];
856                 st->unmap_param = calloc(td->o.iodepth + 1, sizeof(char[16]));
857                 st->unmap_range_count = 0;
858                 st->trim_io_us = calloc(td->o.iodepth, sizeof(struct io_u *));
859         }
860
861         td->io_ops_data = sd;
862
863         /*
864          * we want to do it, regardless of whether odirect is set or not
865          */
866         td->o.override_sync = 1;
867         return 0;
868 }
869
870 static int fio_sgio_type_check(struct thread_data *td, struct fio_file *f)
871 {
872         struct sgio_data *sd = td->io_ops_data;
873         unsigned int bs = 0;
874         unsigned long long max_lba = 0;
875
876         if (f->filetype == FIO_TYPE_BLOCK) {
877                 if (ioctl(f->fd, BLKSSZGET, &bs) < 0) {
878                         td_verror(td, errno, "ioctl");
879                         return 1;
880                 }
881         } else if (f->filetype == FIO_TYPE_CHAR) {
882                 int version, ret;
883
884                 if (ioctl(f->fd, SG_GET_VERSION_NUM, &version) < 0) {
885                         td_verror(td, errno, "ioctl");
886                         return 1;
887                 }
888
889                 ret = fio_sgio_read_capacity(td, &bs, &max_lba);
890                 if (ret) {
891                         td_verror(td, td->error, "fio_sgio_read_capacity");
892                         log_err("ioengine sg unable to read capacity successfully\n");
893                         return 1;
894                 }
895         } else {
896                 td_verror(td, EINVAL, "wrong file type");
897                 log_err("ioengine sg only works on block or character devices\n");
898                 return 1;
899         }
900
901         sd->bs = bs;
902         // Determine size of commands needed based on max_lba
903         if (max_lba >= MAX_10B_LBA) {
904                 dprint(FD_IO, "sgio_type_check: using 16 byte read/write "
905                         "commands for lba above 0x%016llx/0x%016llx\n",
906                         MAX_10B_LBA, max_lba);
907         }
908
909         if (f->filetype == FIO_TYPE_BLOCK) {
910                 td->io_ops->getevents = NULL;
911                 td->io_ops->event = NULL;
912                 td->io_ops->commit = NULL;
913                 /*
914                 ** Setting these functions to null may cause problems
915                 ** with filename=/dev/sda:/dev/sg0 since we are only
916                 ** considering a single file
917                 */
918         }
919         sd->type_checked = 1;
920
921         return 0;
922 }
923
924 static int fio_sgio_open(struct thread_data *td, struct fio_file *f)
925 {
926         struct sgio_data *sd = td->io_ops_data;
927         int ret;
928
929         ret = generic_open_file(td, f);
930         if (ret)
931                 return ret;
932
933         if (sd && !sd->type_checked && fio_sgio_type_check(td, f)) {
934                 ret = generic_close_file(td, f);
935                 return 1;
936         }
937
938         return 0;
939 }
940
941 /*
942  * Build an error string with details about the driver, host or scsi
943  * error contained in the sg header Caller will use as necessary.
944  */
945 static char *fio_sgio_errdetails(struct io_u *io_u)
946 {
947         struct sg_io_hdr *hdr = &io_u->hdr;
948 #define MAXERRDETAIL 1024
949 #define MAXMSGCHUNK  128
950         char *msg, msgchunk[MAXMSGCHUNK];
951         int i;
952
953         msg = calloc(1, MAXERRDETAIL);
954         strcpy(msg, "");
955
956         /*
957          * can't seem to find sg_err.h, so I'll just echo the define values
958          * so others can search on internet to find clearer clues of meaning.
959          */
960         if (hdr->info & SG_INFO_CHECK) {
961                 if (hdr->host_status) {
962                         snprintf(msgchunk, MAXMSGCHUNK, "SG Host Status: 0x%02x; ", hdr->host_status);
963                         strlcat(msg, msgchunk, MAXERRDETAIL);
964                         switch (hdr->host_status) {
965                         case 0x01:
966                                 strlcat(msg, "SG_ERR_DID_NO_CONNECT", MAXERRDETAIL);
967                                 break;
968                         case 0x02:
969                                 strlcat(msg, "SG_ERR_DID_BUS_BUSY", MAXERRDETAIL);
970                                 break;
971                         case 0x03:
972                                 strlcat(msg, "SG_ERR_DID_TIME_OUT", MAXERRDETAIL);
973                                 break;
974                         case 0x04:
975                                 strlcat(msg, "SG_ERR_DID_BAD_TARGET", MAXERRDETAIL);
976                                 break;
977                         case 0x05:
978                                 strlcat(msg, "SG_ERR_DID_ABORT", MAXERRDETAIL);
979                                 break;
980                         case 0x06:
981                                 strlcat(msg, "SG_ERR_DID_PARITY", MAXERRDETAIL);
982                                 break;
983                         case 0x07:
984                                 strlcat(msg, "SG_ERR_DID_ERROR (internal error)", MAXERRDETAIL);
985                                 break;
986                         case 0x08:
987                                 strlcat(msg, "SG_ERR_DID_RESET", MAXERRDETAIL);
988                                 break;
989                         case 0x09:
990                                 strlcat(msg, "SG_ERR_DID_BAD_INTR (unexpected)", MAXERRDETAIL);
991                                 break;
992                         case 0x0a:
993                                 strlcat(msg, "SG_ERR_DID_PASSTHROUGH", MAXERRDETAIL);
994                                 break;
995                         case 0x0b:
996                                 strlcat(msg, "SG_ERR_DID_SOFT_ERROR (driver retry?)", MAXERRDETAIL);
997                                 break;
998                         case 0x0c:
999                                 strlcat(msg, "SG_ERR_DID_IMM_RETRY", MAXERRDETAIL);
1000                                 break;
1001                         case 0x0d:
1002                                 strlcat(msg, "SG_ERR_DID_REQUEUE", MAXERRDETAIL);
1003                                 break;
1004                         case 0x0e:
1005                                 strlcat(msg, "SG_ERR_DID_TRANSPORT_DISRUPTED", MAXERRDETAIL);
1006                                 break;
1007                         case 0x0f:
1008                                 strlcat(msg, "SG_ERR_DID_TRANSPORT_FAILFAST", MAXERRDETAIL);
1009                                 break;
1010                         case 0x10:
1011                                 strlcat(msg, "SG_ERR_DID_TARGET_FAILURE", MAXERRDETAIL);
1012                                 break;
1013                         case 0x11:
1014                                 strlcat(msg, "SG_ERR_DID_NEXUS_FAILURE", MAXERRDETAIL);
1015                                 break;
1016                         case 0x12:
1017                                 strlcat(msg, "SG_ERR_DID_ALLOC_FAILURE", MAXERRDETAIL);
1018                                 break;
1019                         case 0x13:
1020                                 strlcat(msg, "SG_ERR_DID_MEDIUM_ERROR", MAXERRDETAIL);
1021                                 break;
1022                         default:
1023                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1024                                 break;
1025                         }
1026                         strlcat(msg, ". ", MAXERRDETAIL);
1027                 }
1028                 if (hdr->driver_status) {
1029                         snprintf(msgchunk, MAXMSGCHUNK, "SG Driver Status: 0x%02x; ", hdr->driver_status);
1030                         strlcat(msg, msgchunk, MAXERRDETAIL);
1031                         switch (hdr->driver_status & 0x0F) {
1032                         case 0x01:
1033                                 strlcat(msg, "SG_ERR_DRIVER_BUSY", MAXERRDETAIL);
1034                                 break;
1035                         case 0x02:
1036                                 strlcat(msg, "SG_ERR_DRIVER_SOFT", MAXERRDETAIL);
1037                                 break;
1038                         case 0x03:
1039                                 strlcat(msg, "SG_ERR_DRIVER_MEDIA", MAXERRDETAIL);
1040                                 break;
1041                         case 0x04:
1042                                 strlcat(msg, "SG_ERR_DRIVER_ERROR", MAXERRDETAIL);
1043                                 break;
1044                         case 0x05:
1045                                 strlcat(msg, "SG_ERR_DRIVER_INVALID", MAXERRDETAIL);
1046                                 break;
1047                         case 0x06:
1048                                 strlcat(msg, "SG_ERR_DRIVER_TIMEOUT", MAXERRDETAIL);
1049                                 break;
1050                         case 0x07:
1051                                 strlcat(msg, "SG_ERR_DRIVER_HARD", MAXERRDETAIL);
1052                                 break;
1053                         case 0x08:
1054                                 strlcat(msg, "SG_ERR_DRIVER_SENSE", MAXERRDETAIL);
1055                                 break;
1056                         default:
1057                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1058                                 break;
1059                         }
1060                         strlcat(msg, "; ", MAXERRDETAIL);
1061                         switch (hdr->driver_status & 0xF0) {
1062                         case 0x10:
1063                                 strlcat(msg, "SG_ERR_SUGGEST_RETRY", MAXERRDETAIL);
1064                                 break;
1065                         case 0x20:
1066                                 strlcat(msg, "SG_ERR_SUGGEST_ABORT", MAXERRDETAIL);
1067                                 break;
1068                         case 0x30:
1069                                 strlcat(msg, "SG_ERR_SUGGEST_REMAP", MAXERRDETAIL);
1070                                 break;
1071                         case 0x40:
1072                                 strlcat(msg, "SG_ERR_SUGGEST_DIE", MAXERRDETAIL);
1073                                 break;
1074                         case 0x80:
1075                                 strlcat(msg, "SG_ERR_SUGGEST_SENSE", MAXERRDETAIL);
1076                                 break;
1077                         }
1078                         strlcat(msg, ". ", MAXERRDETAIL);
1079                 }
1080                 if (hdr->status) {
1081                         snprintf(msgchunk, MAXMSGCHUNK, "SG SCSI Status: 0x%02x; ", hdr->status);
1082                         strlcat(msg, msgchunk, MAXERRDETAIL);
1083                         // SCSI 3 status codes
1084                         switch (hdr->status) {
1085                         case 0x02:
1086                                 strlcat(msg, "CHECK_CONDITION", MAXERRDETAIL);
1087                                 break;
1088                         case 0x04:
1089                                 strlcat(msg, "CONDITION_MET", MAXERRDETAIL);
1090                                 break;
1091                         case 0x08:
1092                                 strlcat(msg, "BUSY", MAXERRDETAIL);
1093                                 break;
1094                         case 0x10:
1095                                 strlcat(msg, "INTERMEDIATE", MAXERRDETAIL);
1096                                 break;
1097                         case 0x14:
1098                                 strlcat(msg, "INTERMEDIATE_CONDITION_MET", MAXERRDETAIL);
1099                                 break;
1100                         case 0x18:
1101                                 strlcat(msg, "RESERVATION_CONFLICT", MAXERRDETAIL);
1102                                 break;
1103                         case 0x22:
1104                                 strlcat(msg, "COMMAND_TERMINATED", MAXERRDETAIL);
1105                                 break;
1106                         case 0x28:
1107                                 strlcat(msg, "TASK_SET_FULL", MAXERRDETAIL);
1108                                 break;
1109                         case 0x30:
1110                                 strlcat(msg, "ACA_ACTIVE", MAXERRDETAIL);
1111                                 break;
1112                         case 0x40:
1113                                 strlcat(msg, "TASK_ABORTED", MAXERRDETAIL);
1114                                 break;
1115                         default:
1116                                 strlcat(msg, "Unknown", MAXERRDETAIL);
1117                                 break;
1118                         }
1119                         strlcat(msg, ". ", MAXERRDETAIL);
1120                 }
1121                 if (hdr->sb_len_wr) {
1122                         snprintf(msgchunk, MAXMSGCHUNK, "Sense Data (%d bytes):", hdr->sb_len_wr);
1123                         strlcat(msg, msgchunk, MAXERRDETAIL);
1124                         for (i = 0; i < hdr->sb_len_wr; i++) {
1125                                 snprintf(msgchunk, MAXMSGCHUNK, " %02x", hdr->sbp[i]);
1126                                 strlcat(msg, msgchunk, MAXERRDETAIL);
1127                         }
1128                         strlcat(msg, ". ", MAXERRDETAIL);
1129                 }
1130                 if (hdr->resid != 0) {
1131                         snprintf(msgchunk, MAXMSGCHUNK, "SG Driver: %d bytes out of %d not transferred. ", hdr->resid, hdr->dxfer_len);
1132                         strlcat(msg, msgchunk, MAXERRDETAIL);
1133                 }
1134                 if (hdr->cmdp) {
1135                         strlcat(msg, "cdb:", MAXERRDETAIL);
1136                         for (i = 0; i < hdr->cmd_len; i++) {
1137                                 snprintf(msgchunk, MAXMSGCHUNK, " %02x", hdr->cmdp[i]);
1138                                 strlcat(msg, msgchunk, MAXERRDETAIL);
1139                         }
1140                         strlcat(msg, ". ", MAXERRDETAIL);
1141                         if (io_u->ddir == DDIR_TRIM) {
1142                                 unsigned char *param_list = hdr->dxferp;
1143                                 strlcat(msg, "dxferp:", MAXERRDETAIL);
1144                                 for (i = 0; i < hdr->dxfer_len; i++) {
1145                                         snprintf(msgchunk, MAXMSGCHUNK, " %02x", param_list[i]);
1146                                         strlcat(msg, msgchunk, MAXERRDETAIL);
1147                                 }
1148                                 strlcat(msg, ". ", MAXERRDETAIL);
1149                         }
1150                 }
1151         }
1152
1153         if (!(hdr->info & SG_INFO_CHECK) && !strlen(msg))
1154                 strncpy(msg, "SG Driver did not report a Host, Driver or Device check",
1155                         MAXERRDETAIL - 1);
1156
1157         return msg;
1158 }
1159
1160 /*
1161  * get max file size from read capacity.
1162  */
1163 static int fio_sgio_get_file_size(struct thread_data *td, struct fio_file *f)
1164 {
1165         /*
1166          * get_file_size is being called even before sgio_init is
1167          * called, so none of the sg_io structures are
1168          * initialized in the thread_data yet.  So we need to do the
1169          * ReadCapacity without any of those helpers.  One of the effects
1170          * is that ReadCapacity may get called 4 times on each open:
1171          * readcap(10) followed by readcap(16) if needed - just to get
1172          * the file size after the init occurs - it will be called
1173          * again when "type_check" is called during structure
1174          * initialization I'm not sure how to prevent this little
1175          * inefficiency.
1176          */
1177         unsigned int bs = 0;
1178         unsigned long long max_lba = 0;
1179         int ret;
1180
1181         if (fio_file_size_known(f))
1182                 return 0;
1183
1184         if (f->filetype != FIO_TYPE_BLOCK && f->filetype != FIO_TYPE_CHAR) {
1185                 td_verror(td, EINVAL, "wrong file type");
1186                 log_err("ioengine sg only works on block or character devices\n");
1187                 return 1;
1188         }
1189
1190         ret = fio_sgio_read_capacity(td, &bs, &max_lba);
1191         if (ret ) {
1192                 td_verror(td, td->error, "fio_sgio_read_capacity");
1193                 log_err("ioengine sg unable to successfully execute read capacity to get block size and maximum lba\n");
1194                 return 1;
1195         }
1196
1197         f->real_file_size = (max_lba + 1) * bs;
1198         fio_file_set_size_known(f);
1199         return 0;
1200 }
1201
1202
1203 static struct ioengine_ops ioengine = {
1204         .name           = "sg",
1205         .version        = FIO_IOOPS_VERSION,
1206         .init           = fio_sgio_init,
1207         .prep           = fio_sgio_prep,
1208         .queue          = fio_sgio_queue,
1209         .commit         = fio_sgio_commit,
1210         .getevents      = fio_sgio_getevents,
1211         .errdetails     = fio_sgio_errdetails,
1212         .event          = fio_sgio_event,
1213         .cleanup        = fio_sgio_cleanup,
1214         .open_file      = fio_sgio_open,
1215         .close_file     = generic_close_file,
1216         .get_file_size  = fio_sgio_get_file_size,
1217         .flags          = FIO_SYNCIO | FIO_RAWIO,
1218         .options        = options,
1219         .option_struct_size     = sizeof(struct sg_options)
1220 };
1221
1222 #else /* FIO_HAVE_SGIO */
1223
1224 /*
1225  * When we have a proper configure system in place, we simply wont build
1226  * and install this io engine. For now install a crippled version that
1227  * just complains and fails to load.
1228  */
1229 static int fio_sgio_init(struct thread_data fio_unused *td)
1230 {
1231         log_err("fio: ioengine sg not available\n");
1232         return 1;
1233 }
1234
1235 static struct ioengine_ops ioengine = {
1236         .name           = "sg",
1237         .version        = FIO_IOOPS_VERSION,
1238         .init           = fio_sgio_init,
1239 };
1240
1241 #endif
1242
1243 static void fio_init fio_sgio_register(void)
1244 {
1245         register_ioengine(&ioengine);
1246 }
1247
1248 static void fio_exit fio_sgio_unregister(void)
1249 {
1250         unregister_ioengine(&ioengine);
1251 }