X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=engines%2Fsg.c;h=f240755595052684864209cdc5b6982a805fcc2d;hb=d3d378218e9e03411749b65451b32d7a7466ff61;hp=2148e87c190f8c1dfc4f648aecb99796888ca777;hpb=f70afaca743f2971312d9928f069a9ea7daeccf7;p=fio.git diff --git a/engines/sg.c b/engines/sg.c index 2148e87c..f2407555 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -12,9 +12,43 @@ #include #include "../fio.h" +#include "../optgroup.h" #ifdef FIO_HAVE_SGIO + +struct sg_options { + void *pad; + unsigned int readfua; + unsigned int writefua; +}; + +static struct fio_option options[] = { + { + .name = "readfua", + .lname = "sg engine read fua flag support", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct sg_options, readfua), + .help = "Set FUA flag (force unit access) for all Read operations", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_SG, + }, + { + .name = "writefua", + .lname = "sg engine write fua flag support", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct sg_options, writefua), + .help = "Set FUA flag (force unit access) for all Write operations", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_SG, + }, + { + .name = NULL, + }, +}; + #define MAX_10B_LBA 0xFFFFFFFFULL #define SCSI_TIMEOUT_MS 30000 // 30 second timeout; currently no method to override #define MAX_SB 64 // sense block maximum return size @@ -124,7 +158,7 @@ static int fio_sgio_getevents(struct thread_data *td, unsigned int min, } while (left) { - void *p; + char *p; dprint(FD_IO, "sgio_getevents: sd %p: left=%d\n", sd, left); @@ -184,7 +218,7 @@ re_read: if (hdr->info & SG_INFO_CHECK) { struct io_u *io_u; io_u = (struct io_u *)(hdr->usr_ptr); - memcpy((void*)&(io_u->hdr), (void*)hdr, sizeof(struct sg_io_hdr)); + memcpy(&io_u->hdr, hdr, sizeof(struct sg_io_hdr)); sd->events[i]->error = EIO; } } @@ -267,6 +301,7 @@ static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int do_sync) static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) { struct sg_io_hdr *hdr = &io_u->hdr; + struct sg_options *o = td->eo; struct sgio_data *sd = td->io_ops_data; long long nr_blocks, lba; @@ -286,6 +321,10 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) hdr->cmdp[0] = 0x28; // read(10) else hdr->cmdp[0] = 0x88; // read(16) + + if (o->readfua) + hdr->cmdp[1] |= 0x08; + } else if (io_u->ddir == DDIR_WRITE) { sgio_hdr_init(sd, hdr, io_u, 1); @@ -294,6 +333,10 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) hdr->cmdp[0] = 0x2a; // write(10) else hdr->cmdp[0] = 0x8a; // write(16) + + if (o->writefua) + hdr->cmdp[1] |= 0x08; + } else { sgio_hdr_init(sd, hdr, io_u, 0); hdr->dxfer_direction = SG_DXFER_NONE; @@ -572,17 +615,17 @@ static char *fio_sgio_errdetails(struct io_u *io_u) struct sg_io_hdr *hdr = &io_u->hdr; #define MAXERRDETAIL 1024 #define MAXMSGCHUNK 128 - char *msg, msgchunk[MAXMSGCHUNK], *ret = NULL; + char *msg, msgchunk[MAXMSGCHUNK]; int i; msg = calloc(1, MAXERRDETAIL); + strcpy(msg, ""); /* * can't seem to find sg_err.h, so I'll just echo the define values * so others can search on internet to find clearer clues of meaning. */ if (hdr->info & SG_INFO_CHECK) { - ret = msg; if (hdr->host_status) { snprintf(msgchunk, MAXMSGCHUNK, "SG Host Status: 0x%02x; ", hdr->host_status); strlcat(msg, msgchunk, MAXERRDETAIL); @@ -755,14 +798,14 @@ static char *fio_sgio_errdetails(struct io_u *io_u) if (hdr->resid != 0) { snprintf(msgchunk, MAXMSGCHUNK, "SG Driver: %d bytes out of %d not transferred. ", hdr->resid, hdr->dxfer_len); strlcat(msg, msgchunk, MAXERRDETAIL); - ret = msg; } } - if (!ret) - ret = strdup("SG Driver did not report a Host, Driver or Device check"); + if (!(hdr->info & SG_INFO_CHECK) && !strlen(msg)) + strncpy(msg, "SG Driver did not report a Host, Driver or Device check", + MAXERRDETAIL - 1); - return ret; + return msg; } /* @@ -822,6 +865,8 @@ static struct ioengine_ops ioengine = { .close_file = generic_close_file, .get_file_size = fio_sgio_get_file_size, .flags = FIO_SYNCIO | FIO_RAWIO, + .options = options, + .option_struct_size = sizeof(struct sg_options) }; #else /* FIO_HAVE_SGIO */