X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=engines%2Fsg.c;h=b51edb078bbb06a04ce63130bdabf1d9586ed0e9;hb=9917adb5d3b9c480ac710af4bc2c9c0421c6a5df;hp=a1a6de4ce248dd680dc9d2f709479422de24b6de;hpb=998baa29f571df9d2e4b626bedd317a2fd28c68a;p=fio.git diff --git a/engines/sg.c b/engines/sg.c index a1a6de4c..b51edb07 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -60,20 +60,40 @@ #ifdef FIO_HAVE_SGIO +#ifndef SGV4_FLAG_HIPRI +#define SGV4_FLAG_HIPRI 0x800 +#endif + enum { FIO_SG_WRITE = 1, - FIO_SG_WRITE_VERIFY = 2, - FIO_SG_WRITE_SAME = 3 + FIO_SG_WRITE_VERIFY, + FIO_SG_WRITE_SAME, + FIO_SG_WRITE_SAME_NDOB, + FIO_SG_WRITE_STREAM, + FIO_SG_VERIFY_BYTCHK_00, + FIO_SG_VERIFY_BYTCHK_01, + FIO_SG_VERIFY_BYTCHK_11, }; struct sg_options { void *pad; + unsigned int hipri; unsigned int readfua; unsigned int writefua; unsigned int write_mode; + uint16_t stream_id; }; 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", @@ -106,18 +126,58 @@ static struct fio_option options[] = { .oval = FIO_SG_WRITE, .help = "Issue standard SCSI WRITE commands", }, - { .ival = "verify", + { .ival = "write_and_verify", .oval = FIO_SG_WRITE_VERIFY, .help = "Issue SCSI WRITE AND VERIFY commands", }, - { .ival = "same", + { .ival = "verify", + .oval = FIO_SG_WRITE_VERIFY, + .help = "Issue SCSI WRITE AND VERIFY commands. This " + "option is deprecated. Use write_and_verify instead.", + }, + { .ival = "write_same", .oval = FIO_SG_WRITE_SAME, .help = "Issue SCSI WRITE SAME commands", }, + { .ival = "same", + .oval = FIO_SG_WRITE_SAME, + .help = "Issue SCSI WRITE SAME commands. This " + "option is deprecated. Use write_same instead.", + }, + { .ival = "write_same_ndob", + .oval = FIO_SG_WRITE_SAME_NDOB, + .help = "Issue SCSI WRITE SAME(16) commands with NDOB flag set", + }, + { .ival = "verify_bytchk_00", + .oval = FIO_SG_VERIFY_BYTCHK_00, + .help = "Issue SCSI VERIFY commands with BYTCHK set to 00", + }, + { .ival = "verify_bytchk_01", + .oval = FIO_SG_VERIFY_BYTCHK_01, + .help = "Issue SCSI VERIFY commands with BYTCHK set to 01", + }, + { .ival = "verify_bytchk_11", + .oval = FIO_SG_VERIFY_BYTCHK_11, + .help = "Issue SCSI VERIFY commands with BYTCHK set to 11", + }, + { .ival = "write_stream", + .oval = FIO_SG_WRITE_STREAM, + .help = "Issue SCSI WRITE STREAM(16) commands", + }, }, .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_SG, }, + { + .name = "stream_id", + .lname = "stream id for WRITE STREAM(16) commands", + .type = FIO_OPT_INT, + .off1 = offsetof(struct sg_options, stream_id), + .help = "Stream ID for WRITE STREAM(16) commands", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_SG, + }, { .name = NULL, }, @@ -457,10 +517,9 @@ static enum fio_q_status fio_sgio_rw_doio(struct thread_data *td, if (__io_u == io_u) break; - if (io_u_sync_complete(td, __io_u)) { - ret = -1; + if (io_u_sync_complete(td, __io_u)) break; - } + } while (1); return FIO_Q_COMPLETED; @@ -489,9 +548,9 @@ static enum fio_q_status fio_sgio_doio(struct thread_data *td, } static void fio_sgio_rw_lba(struct sg_io_hdr *hdr, unsigned long long lba, - unsigned long long nr_blocks) + unsigned long long nr_blocks, bool override16) { - if (lba < MAX_10B_LBA) { + if (lba < MAX_10B_LBA && !override16) { sgio_set_be32((uint32_t) lba, &hdr->cmdp[2]); sgio_set_be16((uint16_t) nr_blocks, &hdr->cmdp[7]); } else { @@ -527,10 +586,12 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) else hdr->cmdp[0] = 0x88; // read(16) + if (o->hipri) + hdr->flags |= SGV4_FLAG_HIPRI; if (o->readfua) hdr->cmdp[1] |= 0x08; - fio_sgio_rw_lba(hdr, lba, nr_blocks); + fio_sgio_rw_lba(hdr, lba, nr_blocks, false); } else if (io_u->ddir == DDIR_WRITE) { sgio_hdr_init(sd, hdr, io_u, 1); @@ -542,6 +603,8 @@ 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->hipri) + hdr->flags |= SGV4_FLAG_HIPRI; if (o->writefua) hdr->cmdp[1] |= 0x08; break; @@ -559,9 +622,46 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) else hdr->cmdp[0] = 0x93; // write same(16) break; + case FIO_SG_WRITE_SAME_NDOB: + hdr->cmdp[0] = 0x93; // write same(16) + hdr->cmdp[1] |= 0x1; // no data output buffer + hdr->dxfer_len = 0; + break; + case FIO_SG_WRITE_STREAM: + hdr->cmdp[0] = 0x9a; // write stream (16) + if (o->writefua) + hdr->cmdp[1] |= 0x08; + sgio_set_be64(lba, &hdr->cmdp[2]); + sgio_set_be16(o->stream_id, &hdr->cmdp[10]); + sgio_set_be16((uint16_t) nr_blocks, &hdr->cmdp[12]); + break; + case FIO_SG_VERIFY_BYTCHK_00: + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x2f; // VERIFY(10) + else + hdr->cmdp[0] = 0x8f; // VERIFY(16) + hdr->dxfer_len = 0; + break; + case FIO_SG_VERIFY_BYTCHK_01: + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x2f; // VERIFY(10) + else + hdr->cmdp[0] = 0x8f; // VERIFY(16) + hdr->cmdp[1] |= 0x02; // BYTCHK = 01b + break; + case FIO_SG_VERIFY_BYTCHK_11: + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x2f; // VERIFY(10) + else + hdr->cmdp[0] = 0x8f; // VERIFY(16) + hdr->cmdp[1] |= 0x06; // BYTCHK = 11b + hdr->dxfer_len = sd->bs; + break; }; - fio_sgio_rw_lba(hdr, lba, nr_blocks); + if (o->write_mode != FIO_SG_WRITE_STREAM) + fio_sgio_rw_lba(hdr, lba, nr_blocks, + o->write_mode == FIO_SG_WRITE_SAME_NDOB); } else if (io_u->ddir == DDIR_TRIM) { struct sgio_trim *st; @@ -865,6 +965,7 @@ static int fio_sgio_init(struct thread_data *td) { struct sgio_data *sd; struct sgio_trim *st; + struct sg_io_hdr *h3p; int i; sd = calloc(1, sizeof(*sd)); @@ -880,12 +981,13 @@ static int fio_sgio_init(struct thread_data *td) #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; @@ -962,7 +1064,7 @@ static int fio_sgio_open(struct thread_data *td, struct fio_file *f) if (sd && !sd->type_checked && fio_sgio_type_check(td, f)) { ret = generic_close_file(td, f); - return 1; + return ret; } return 0;