The following changes since commit 28c43a89ae13b648dd37269d288fbbea2550faa8: Fix comment on SCSI commands (2017-01-06 11:26:04 -0700) are available in the git repository at: git://git.kernel.dk/fio.git master for you to fetch changes up to 9bae252254d0ce37a144cb4c8d2cb4222d539a9e: Python style/portability fix (2017-01-10 13:20:30 -0700) ---------------------------------------------------------------- Tomohiro Kusumi (10): Bring in additional sg error cases from Linux kernel (and sg3) header Staticize pmemblk ioengine_ops Fix conditional/message for max lba for sg ioengine Non functional fixup for 16 bytes read capacity for sg ioengine Mention sg ioengine requires filename option Fix compile time errors for skeleton_external ioengine Partly revert 8172fe97 in 2008 (A few debug debug log fixes) Add missing trailing \n in dprint() Fix README regarding fio snapshots Python style/portability fix HOWTO | 3 ++- README | 5 +++-- engines/pmemblk.c | 2 +- engines/sg.c | 48 ++++++++++++++++++++++++++++++++------------- engines/skeleton_external.c | 8 ++++---- ioengine.h | 9 +++------ iolog.c | 2 +- tools/fiologparser.py | 14 ++++++------- 8 files changed, 55 insertions(+), 36 deletions(-) --- Diff of recent changes: diff --git a/HOWTO b/HOWTO index 4cc733f..33f8718 100644 --- a/HOWTO +++ b/HOWTO @@ -819,7 +819,8 @@ ioengine=str Defines how the job issues io to the file. The following synchronous using the SG_IO ioctl, or if the target is an sg character device we use read(2) and write(2) for asynchronous - io. + io. Requires filename option to specify either + block or character devices. null Doesn't transfer any data, just pretends to. This is mainly used to exercise fio diff --git a/README b/README index 875d2be..31d53fe 100644 --- a/README +++ b/README @@ -21,7 +21,8 @@ If git:// does not work, use the http protocol instead: http://git.kernel.dk/fio.git -Snapshots are frequently generated and include the git meta data as well. +Snapshots are frequently generated and fio-git-*.tar.gz include the git +meta data as well. Other tarballs are archives of official fio releases. Snapshots can download from: http://brick.kernel.dk/snaps/ @@ -262,7 +263,7 @@ the copyright and license requirements currently apply to examples/ files. Client/server ------------- +------------- Normally fio is invoked as a stand-alone application on the machine where the IO workload should be generated. However, the frontend and diff --git a/engines/pmemblk.c b/engines/pmemblk.c index ca72697..5439da0 100644 --- a/engines/pmemblk.c +++ b/engines/pmemblk.c @@ -482,7 +482,7 @@ static int fio_pmemblk_unlink_file(struct thread_data *td, struct fio_file *f) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "pmemblk", .version = FIO_IOOPS_VERSION, .queue = fio_pmemblk_queue, diff --git a/engines/sg.c b/engines/sg.c index 2ad3394..3f7d911 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -20,7 +20,7 @@ #define MAX_SB 64 // sense block maximum return size struct sgio_cmd { - unsigned char cdb[16]; // increase to support 16 byte commands + unsigned char cdb[16]; // enhanced from 10 to support 16 byte commands unsigned char sb[MAX_SB]; // add sense block to commands int nr; }; @@ -32,7 +32,6 @@ struct sgio_data { int *fd_flags; void *sgbuf; unsigned int bs; - long long max_lba; int type_checked; }; @@ -309,7 +308,6 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) * blocks on medium. */ if (hdr->dxfer_direction != SG_DXFER_NONE) { - if (lba < MAX_10B_LBA) { hdr->cmdp[2] = (unsigned char) ((lba >> 24) & 0xff); hdr->cmdp[3] = (unsigned char) ((lba >> 16) & 0xff); @@ -416,12 +414,11 @@ static int fio_sgio_read_capacity(struct thread_data *td, unsigned int *bs, } *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]) & 0x00000000FFFFFFFFULL; // for some reason max_lba is being sign extended even though unsigned. - + *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. /* - * If max lba is 0xFFFFFFFF, then need to retry with - * 16 byteread capacity + * If max lba masked by MAX_10B_LBA equals MAX_10B_LBA, + * then need to retry with 16 byte Read Capacity command. */ if (*max_lba == MAX_10B_LBA) { hdr.cmd_len = 16; @@ -507,7 +504,6 @@ static int fio_sgio_type_check(struct thread_data *td, struct fio_file *f) unsigned int bs = 0; unsigned long long max_lba = 0; - if (f->filetype == FIO_TYPE_BD) { if (ioctl(f->fd, BLKSSZGET, &bs) < 0) { td_verror(td, errno, "ioctl"); @@ -529,18 +525,18 @@ static int fio_sgio_type_check(struct thread_data *td, struct fio_file *f) } } else { td_verror(td, EINVAL, "wrong file type"); - log_err("ioengine sg only works on block devices\n"); + log_err("ioengine sg only works on block or character devices\n"); return 1; } sd->bs = bs; // Determine size of commands needed based on max_lba - sd->max_lba = max_lba; - if (max_lba > MAX_10B_LBA) { - dprint(FD_IO, "sgio_type_check: using 16 byte operations: max_lba = 0x%016llx\n", max_lba); + if (max_lba >= MAX_10B_LBA) { + dprint(FD_IO, "sgio_type_check: using 16 byte read/write " + "commands for lba above 0x%016llx/0x%016llx\n", + MAX_10B_LBA, max_lba); } - if (f->filetype == FIO_TYPE_BD) { td->io_ops->getevents = NULL; td->io_ops->event = NULL; @@ -630,6 +626,24 @@ static char *fio_sgio_errdetails(struct io_u *io_u) case 0x0d: strlcat(msg, "SG_ERR_DID_REQUEUE", MAXERRDETAIL); break; + case 0x0e: + strlcat(msg, "SG_ERR_DID_TRANSPORT_DISRUPTED", MAXERRDETAIL); + break; + case 0x0f: + strlcat(msg, "SG_ERR_DID_TRANSPORT_FAILFAST", MAXERRDETAIL); + break; + case 0x10: + strlcat(msg, "SG_ERR_DID_TARGET_FAILURE", MAXERRDETAIL); + break; + case 0x11: + strlcat(msg, "SG_ERR_DID_NEXUS_FAILURE", MAXERRDETAIL); + break; + case 0x12: + strlcat(msg, "SG_ERR_DID_ALLOC_FAILURE", MAXERRDETAIL); + break; + case 0x13: + strlcat(msg, "SG_ERR_DID_MEDIUM_ERROR", MAXERRDETAIL); + break; default: strlcat(msg, "Unknown", MAXERRDETAIL); break; @@ -775,6 +789,12 @@ static int fio_sgio_get_file_size(struct thread_data *td, struct fio_file *f) if (fio_file_size_known(f)) return 0; + if (f->filetype != FIO_TYPE_BD && f->filetype != FIO_TYPE_CHAR) { + td_verror(td, EINVAL, "wrong file type"); + log_err("ioengine sg only works on block or character devices\n"); + return 1; + } + ret = fio_sgio_read_capacity(td, &bs, &max_lba); if (ret ) { td_verror(td, td->error, "fio_sgio_read_capacity"); @@ -800,7 +820,7 @@ static struct ioengine_ops ioengine = { .cleanup = fio_sgio_cleanup, .open_file = fio_sgio_open, .close_file = generic_close_file, - .get_file_size = fio_sgio_get_file_size, // generic_get_file_size + .get_file_size = fio_sgio_get_file_size, .flags = FIO_SYNCIO | FIO_RAWIO, }; diff --git a/engines/skeleton_external.c b/engines/skeleton_external.c index 63a6f8d..4bebcc4 100644 --- a/engines/skeleton_external.c +++ b/engines/skeleton_external.c @@ -109,11 +109,11 @@ static void fio_skeleton_cleanup(struct thread_data *td) /* * Hook for opening the given file. Unless the engine has special - * needs, it usually just provides generic_file_open() as the handler. + * needs, it usually just provides generic_open_file() as the handler. */ static int fio_skeleton_open(struct thread_data *td, struct fio_file *f) { - return generic_file_open(td, f); + return generic_open_file(td, f); } /* @@ -121,12 +121,12 @@ static int fio_skeleton_open(struct thread_data *td, struct fio_file *f) */ static int fio_skeleton_close(struct thread_data *td, struct fio_file *f) { - generic_file_close(td, f); + return generic_close_file(td, f); } /* * Note that the structure is exported, so that fio can get it via - * dlsym(..., "ioengine"); + * dlsym(..., "ioengine"); for (and only for) external engines. */ struct ioengine_ops ioengine = { .name = "engine_name", diff --git a/ioengine.h b/ioengine.h index 08e8fab..89873e7 100644 --- a/ioengine.h +++ b/ioengine.h @@ -238,12 +238,9 @@ static inline void dprint_io_u(struct io_u *io_u, const char *p) dprint(FD_IO, "%s: io_u %p: off=%llu/len=%lu/ddir=%d", p, io_u, (unsigned long long) io_u->offset, io_u->buflen, io_u->ddir); - if (fio_debug & (1 << FD_IO)) { - if (f) - log_info("/%s", f->file_name); - - log_info("\n"); - } + if (f) + dprint(FD_IO, "/%s", f->file_name); + dprint(FD_IO, "\n"); } #else #define dprint_io_u(io_u, p) diff --git a/iolog.c b/iolog.c index 25d8dd0..2e8da13 100644 --- a/iolog.c +++ b/iolog.c @@ -277,7 +277,7 @@ restart: overlap = 1; if (overlap) { - dprint(FD_IO, "iolog: overlap %llu/%lu, %llu/%lu", + dprint(FD_IO, "iolog: overlap %llu/%lu, %llu/%lu\n", __ipo->offset, __ipo->len, ipo->offset, ipo->len); td->io_hist_len--; diff --git a/tools/fiologparser.py b/tools/fiologparser.py index 685f419..5a95009 100755 --- a/tools/fiologparser.py +++ b/tools/fiologparser.py @@ -45,7 +45,7 @@ def print_full(ctx, series): while (start < ftime): end = ftime if ftime < end else end results = [ts.get_value(start, end) for ts in series] - print "%s, %s" % (end, ', '.join(["%0.3f" % i for i in results])) + print("%s, %s" % (end, ', '.join(["%0.3f" % i for i in results]))) start += ctx.interval end += ctx.interval @@ -57,7 +57,7 @@ def print_sums(ctx, series): while (start < ftime): end = ftime if ftime < end else end results = [ts.get_value(start, end) for ts in series] - print "%s, %0.3f" % (end, sum(results)) + print("%s, %0.3f" % (end, sum(results))) start += ctx.interval end += ctx.interval @@ -69,7 +69,7 @@ def print_averages(ctx, series): while (start < ftime): end = ftime if ftime < end else end results = [ts.get_value(start, end) for ts in series] - print "%s, %0.3f" % (end, float(sum(results))/len(results)) + print("%s, %0.3f" % (end, float(sum(results))/len(results))) start += ctx.interval end += ctx.interval @@ -147,11 +147,11 @@ def print_default(ctx, series): end += ctx.interval total = 0 - for i in xrange(0, len(averages)): + for i in range(0, len(averages)): total += averages[i]*weights[i] - print '%0.3f' % (total/sum(weights)) + print('%0.3f' % (total/sum(weights))) -class TimeSeries(): +class TimeSeries(object): def __init__(self, ctx, fn): self.ctx = ctx self.last = None @@ -185,7 +185,7 @@ class TimeSeries(): value += sample.get_contribution(start, end) return value -class Sample(): +class Sample(object): def __init__(self, ctx, start, end, value): self.ctx = ctx self.start = start -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html