X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fsg.c;h=06cd19463b309124e4f75b95eb5ade8d50adb53b;hp=f240755595052684864209cdc5b6982a805fcc2d;hb=12223a35ac7d975d7c2950c664d8caf7f9c065bf;hpb=d3d378218e9e03411749b65451b32d7a7466ff61 diff --git a/engines/sg.c b/engines/sg.c index f2407555..06cd1946 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -8,19 +8,24 @@ #include #include #include -#include -#include +#include #include "../fio.h" #include "../optgroup.h" #ifdef FIO_HAVE_SGIO +enum { + FIO_SG_WRITE = 1, + FIO_SG_WRITE_VERIFY = 2, + FIO_SG_WRITE_SAME = 3 +}; struct sg_options { void *pad; unsigned int readfua; unsigned int writefua; + unsigned int write_mode; }; static struct fio_option options[] = { @@ -44,6 +49,30 @@ static struct fio_option options[] = { .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_SG, }, + { + .name = "sg_write_mode", + .lname = "specify sg write mode", + .type = FIO_OPT_STR, + .off1 = offsetof(struct sg_options, write_mode), + .help = "Specify SCSI WRITE mode", + .def = "write", + .posval = { + { .ival = "write", + .oval = FIO_SG_WRITE, + .help = "Issue standard SCSI WRITE commands", + }, + { .ival = "verify", + .oval = FIO_SG_WRITE_VERIFY, + .help = "Issue SCSI WRITE AND VERIFY commands", + }, + { .ival = "same", + .oval = FIO_SG_WRITE_SAME, + .help = "Issue SCSI WRITE SAME commands", + }, + }, + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_SG, + }, { .name = NULL, }, @@ -237,8 +266,9 @@ re_read: return r; } -static int fio_sgio_ioctl_doio(struct thread_data *td, - struct fio_file *f, struct io_u *io_u) +static enum fio_q_status fio_sgio_ioctl_doio(struct thread_data *td, + struct fio_file *f, + struct io_u *io_u) { struct sgio_data *sd = td->io_ops_data; struct sg_io_hdr *hdr = &io_u->hdr; @@ -288,11 +318,11 @@ static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int do_sync) if (f->filetype == FIO_TYPE_BLOCK) { ret = fio_sgio_ioctl_doio(td, f, io_u); - td->error = io_u->error; + td_verror(td, io_u->error, __func__); } else { ret = fio_sgio_rw_doio(f, io_u, do_sync); if (do_sync) - td->error = io_u->error; + td_verror(td, io_u->error, __func__); } return ret; @@ -329,14 +359,30 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) sgio_hdr_init(sd, hdr, io_u, 1); hdr->dxfer_direction = SG_DXFER_TO_DEV; - if (lba < MAX_10B_LBA) - hdr->cmdp[0] = 0x2a; // write(10) - else - hdr->cmdp[0] = 0x8a; // write(16) - - if (o->writefua) - hdr->cmdp[1] |= 0x08; - + switch(o->write_mode) { + case FIO_SG_WRITE: + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x2a; // write(10) + else + hdr->cmdp[0] = 0x8a; // write(16) + if (o->writefua) + hdr->cmdp[1] |= 0x08; + break; + case FIO_SG_WRITE_VERIFY: + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x2e; // write and verify(10) + else + hdr->cmdp[0] = 0x8e; // write and verify(16) + break; + // BYTCHK is disabled by virtue of the memset in sgio_hdr_init + case FIO_SG_WRITE_SAME: + hdr->dxfer_len = sd->bs; + if (lba < MAX_10B_LBA) + hdr->cmdp[0] = 0x41; // write same(10) + else + hdr->cmdp[0] = 0x93; // write same(16) + break; + }; } else { sgio_hdr_init(sd, hdr, io_u, 0); hdr->dxfer_direction = SG_DXFER_NONE; @@ -378,7 +424,8 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) return 0; } -static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u) +static enum fio_q_status fio_sgio_queue(struct thread_data *td, + struct io_u *io_u) { struct sg_io_hdr *hdr = &io_u->hdr; int ret, do_sync = 0; @@ -456,8 +503,10 @@ static int fio_sgio_read_capacity(struct thread_data *td, unsigned int *bs, return ret; } - *bs = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; - *max_lba = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) & MAX_10B_LBA; // for some reason max_lba is being sign extended even though unsigned. + *bs = ((unsigned long) buf[4] << 24) | ((unsigned long) buf[5] << 16) | + ((unsigned long) buf[6] << 8) | (unsigned long) buf[7]; + *max_lba = ((unsigned long) buf[0] << 24) | ((unsigned long) buf[1] << 16) | + ((unsigned long) buf[2] << 8) | (unsigned long) buf[3]; /* * If max lba masked by MAX_10B_LBA equals MAX_10B_LBA,