#ifdef FIO_HAVE_SGIO
+#ifndef SGV4_FLAG_HIPRI
+#define SGV4_FLAG_HIPRI 0x800
+#endif
+
enum {
FIO_SG_WRITE = 1,
FIO_SG_WRITE_VERIFY = 2,
struct sg_options {
void *pad;
+ unsigned int hipri;
unsigned int readfua;
unsigned int writefua;
unsigned int write_mode;
};
static struct fio_option options[] = {
+ {
+ .name = "hipri",
+ .lname = "High Priority",
+ .type = FIO_OPT_STR_SET,
+ .off1 = offsetof(struct sg_options, hipri),
+ .help = "Use polled IO completions",
+ .category = FIO_OPT_C_ENGINE,
+ .group = FIO_OPT_G_SG,
+ },
{
.name = "readfua",
.lname = "sg engine read fua flag support",
#endif
};
-static inline uint16_t sgio_get_be16(uint8_t *buf)
-{
- return be16_to_cpu(*((uint16_t *) buf));
-}
-
static inline uint32_t sgio_get_be32(uint8_t *buf)
{
return be32_to_cpu(*((uint32_t *) buf));
return FIO_Q_COMPLETED;
}
-static enum fio_q_status fio_sgio_rw_doio(struct fio_file *f,
+static enum fio_q_status fio_sgio_rw_doio(struct thread_data *td,
+ struct fio_file *f,
struct io_u *io_u, int do_sync)
{
struct sg_io_hdr *hdr = &io_u->hdr;
return ret;
if (do_sync) {
- ret = read(f->fd, hdr, sizeof(*hdr));
- if (ret < 0)
- return ret;
+ /*
+ * We can't just read back the first command that completes
+ * and assume it's the one we need, it could be any command
+ * that is inflight.
+ */
+ do {
+ struct io_u *__io_u;
- /* record if an io error occurred */
- if (hdr->info & SG_INFO_CHECK)
- io_u->error = EIO;
+ ret = read(f->fd, hdr, sizeof(*hdr));
+ if (ret < 0)
+ return ret;
+
+ __io_u = hdr->usr_ptr;
+
+ /* record if an io error occurred */
+ if (hdr->info & SG_INFO_CHECK)
+ __io_u->error = EIO;
+
+ if (__io_u == io_u)
+ break;
+
+ if (io_u_sync_complete(td, __io_u))
+ break;
+
+ } while (1);
return FIO_Q_COMPLETED;
}
if (f->filetype == FIO_TYPE_BLOCK) {
ret = fio_sgio_ioctl_doio(td, f, io_u);
- td_verror(td, io_u->error, __func__);
+ if (io_u->error)
+ td_verror(td, io_u->error, __func__);
} else {
- ret = fio_sgio_rw_doio(f, io_u, do_sync);
- if (do_sync)
+ ret = fio_sgio_rw_doio(td, f, io_u, do_sync);
+ if (io_u->error && do_sync)
td_verror(td, io_u->error, __func__);
}
else
hdr->cmdp[0] = 0x88; // read(16)
+ if (o->hipri)
+ hdr->flags |= SGV4_FLAG_HIPRI;
if (o->readfua)
hdr->cmdp[1] |= 0x08;
hdr->cmdp[0] = 0x2a; // write(10)
else
hdr->cmdp[0] = 0x8a; // write(16)
+ if (o->hipri)
+ hdr->flags |= SGV4_FLAG_HIPRI;
if (o->writefua)
hdr->cmdp[1] |= 0x08;
break;
sd->current_queue = -1;
- ret = fio_sgio_rw_doio(io_u->file, io_u, 0);
+ ret = fio_sgio_rw_doio(td, io_u->file, io_u, 0);
if (ret < 0 || hdr->status) {
int error;
{
struct sgio_data *sd;
struct sgio_trim *st;
+ struct sg_io_hdr *h3p;
int i;
sd = calloc(1, sizeof(*sd));
#ifdef FIO_SGIO_DEBUG
sd->trim_queue_map = calloc(td->o.iodepth, sizeof(int));
#endif
- for (i = 0; i < td->o.iodepth; i++) {
+ for (i = 0, h3p = sd->sgbuf; i < td->o.iodepth; i++, ++h3p) {
sd->trim_queues[i] = calloc(1, sizeof(struct sgio_trim));
st = sd->trim_queues[i];
st->unmap_param = calloc(td->o.iodepth + 1, sizeof(char[16]));
st->unmap_range_count = 0;
st->trim_io_us = calloc(td->o.iodepth, sizeof(struct io_u *));
+ h3p->interface_id = 'S';
}
td->io_ops_data = sd;
if (sd && !sd->type_checked && fio_sgio_type_check(td, f)) {
ret = generic_close_file(td, f);
- return 1;
+ return ret;
}
return 0;
}
if (!(hdr->info & SG_INFO_CHECK) && !strlen(msg))
- strncpy(msg, "SG Driver did not report a Host, Driver or Device check",
- MAXERRDETAIL - 1);
+ snprintf(msg, MAXERRDETAIL, "%s",
+ "SG Driver did not report a Host, Driver or Device check");
return msg;
}