diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2019-04-29 07:13:59 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2019-04-29 07:13:59 +0000 |
commit | c3da9a6b41cbae7940180645721a35becdd5bc99 (patch) | |
tree | 6704c41130a47d9b3bd9df2920dab9626f8754c1 /testing | |
parent | 7dff7ae9433763457872082271aac0487e14d158 (diff) | |
download | sg3_utils-c3da9a6b41cbae7940180645721a35becdd5bc99.tar.gz |
scripts: update 54-before-scsi-sg3_id.rules; more testing tweaks
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@820 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'testing')
-rw-r--r-- | testing/sg_tst_async.cpp | 153 | ||||
-rw-r--r-- | testing/sgh_dd.cpp | 6 | ||||
-rw-r--r-- | testing/uapi_sg.h | 43 |
3 files changed, 124 insertions, 78 deletions
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp index e33d8ec0..8638ceec 100644 --- a/testing/sg_tst_async.cpp +++ b/testing/sg_tst_async.cpp @@ -89,7 +89,7 @@ #include "sg_pt.h" #include "sg_cmds.h" -static const char * version_str = "1.28 20190414"; +static const char * version_str = "1.32 20190427"; static const char * util_name = "sg_tst_async"; /* This is a test program for checking the async usage of the Linux sg @@ -134,6 +134,7 @@ using namespace std::chrono; #define DEF_NUM_PER_THREAD 1000 #define DEF_NUM_THREADS 4 #define DEF_WAIT_MS 10 /* 0: yield or no wait */ +#define DEF_NANOSEC_WAIT 25000 /* 25 microsecs */ #define DEF_TIMEOUT_MS 20000 /* 20 seconds */ #define DEF_LB_SZ 512 #define DEF_BLOCKING 0 @@ -269,6 +270,7 @@ static struct option long_options[] = { {"generic_sync", no_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"lba", required_argument, 0, 'l'}, + {"lbsz", required_argument, 0, 'L'}, {"maxqpt", required_argument, 0, 'M'}, {"mmap-io", no_argument, 0, 'm'}, {"mmap_io", no_argument, 0, 'm'}, @@ -299,17 +301,17 @@ static void usage(void) { printf("Usage: %s [--cmd-time] [--direct] [--force] [--generic-sync]\n" - " [--help] [--lba=LBA+] [--maxqpt=QPT] " - "[--mmap-io]\n" - " [--numpt=NPT] [--noxfer] [--override=OVN] " - "[--pack-id]\n" - " [--qat=AT] [-qfav=FAV] [--read] [--stats] " - "[--submit]\n" - " [--szlb=LB[,NLBS]] [--tnum=NT] [--tur] " - "[--v3]\n" - " [--v4] [--verbose] [--version] [--wait=MS] " - "[--write]\n" - " <sg_disk_device>*\n", + " [--help] [--lba=LBA+] [--lbsz=LBSZ] " + "[--maxqpt=QPT]\n" + " [--mmap-io] [--numpt=NPT] [--noxfer] " + "[--override=OVN]\n" + " [--pack-id] [--qat=AT] [-qfav=FAV] [--read] " + "[--stats]\n" + " [--submit] [--szlb=LB[,NLBS]] [--tnum=NT] " + "[--tur]\n" + " [--v3] [--v4] [--verbose] [--version] " + "[--wait=MS]\n" + " [--write] <sg_disk_device>*\n", util_name); printf(" where\n"); printf(" --cmd-time|-c calculate per command average time (ns)\n"); @@ -328,6 +330,9 @@ usage(void) "(inclusive)\n" " if hi_lba=-1 assume last block on " "device\n"); + printf(" --lbsz=LBSZ|-L LBSZ logical block size in bytes (def: " + "512)\n" + " should be power of 2 (0 --> 512)\n"); printf(" --maxqpt=QPT|-M QPT maximum commands queued per thread " "(def:%d)\n", MAX_Q_PER_FD); printf(" --mmap-io|-m mmap-ed IO (1 cmd outstanding per " @@ -373,7 +378,7 @@ usage(void) "by each READ and WRITE; zeros are written. If a\nlogical block " "range is given, a uniform distribution generates a pseudo\n" "random sequence of LBAs. Set environment variable\n" - "SG3_UTILS_LINUX_NANO to get command timings in nanoseconds\n"); + "SG3_UTILS_LINUX_NANO to get command timings in nanoseconds\n"); } #ifdef __GNUC__ @@ -501,7 +506,7 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba, ptp->flags = flags; for (int k = 0; - (submit ? ioctl(sg_fd, SG_IOSUBMIT, ptp) : + (submit ? ioctl(sg_fd, SG_IOSUBMIT_V3, ptp) : write(sg_fd, ptp, sizeof(*ptp)) < 0); ++k) { if ((ENOMEM == errno) && (k < MAX_CONSEC_NOMEMS)) { @@ -527,9 +532,9 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba, } static int -finish_sg3_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force, - int & pack_id, bool receive, int wait_ms, - unsigned int & eagains, unsigned int & nanosecs) +finish_sg3_cmd(int sg_fd, command2execute cmd2exe, int & pack_id, + bool receive, int wait_ms, unsigned int & eagains, + unsigned int & nanosecs) { bool ok; int res, k; @@ -568,17 +573,15 @@ finish_sg3_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force, ptp->pack_id = pack_id; k = 0; - while ((((res = receive ? ioctl(sg_fd, SG_IORECEIVE, ptp) : + while ((((res = receive ? ioctl(sg_fd, SG_IORECEIVE_V3, ptp) : read(sg_fd, ptp, sizeof(*ptp)))) < 0) && (EAGAIN == errno)) { ++eagains; - if (pack_id_force) { - ++k; - if (k > 10000) { - pr2serr_lk("%s: unable to find pack_id=%d\n", __func__, - pack_id); - return -1; /* crash out */ - } + ++k; + if (k > 10000) { + pr2serr_lk("%s: sg_fd=%d: after %d EAGAINs, unable to find " + "pack_id=%d\n", __func__, sg_fd, k, pack_id); + return -1; /* crash out */ } if (wait_ms > 0) this_thread::sleep_for(milliseconds{wait_ms}); @@ -696,9 +699,9 @@ start_sg4_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba, } static int -finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force, - int & pack_id, bool receive, int wait_ms, - unsigned int & eagains, unsigned int & nanosecs) +finish_sg4_cmd(int sg_fd, command2execute cmd2exe, int & pack_id, + bool receive, int wait_ms, unsigned int & eagains, + unsigned int & nanosecs) { bool ok; int res, k; @@ -725,7 +728,7 @@ finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force, np = "WRITE(16)"; break; } - ptp->guard = 'S'; + ptp->guard = 'Q'; ptp->max_response_len = sizeof(sense_buffer); ptp->response = (uint64_t)sense_buffer; ptp->timeout = DEF_TIMEOUT_MS; @@ -736,13 +739,11 @@ finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force, while ((((res = ioctl(sg_fd, SG_IORECEIVE, ptp))) < 0) && (EAGAIN == errno)) { ++eagains; - if (pack_id_force) { - ++k; - if (k > 10000) { - pr2serr_lk("%s: unable to find pack_id=%d\n", __func__, - pack_id); - return -1; /* crash out */ - } + ++k; + if (k > 10000) { + pr2serr_lk("%s: sg_fd=%d: after %d EAGAINs, unable to find " + "pack_id=%d\n", __func__, sg_fd, k, pack_id); + return -1; /* crash out */ } if (wait_ms > 0) this_thread::sleep_for(milliseconds{wait_ms}); @@ -956,7 +957,10 @@ work_thread(int id, struct opts_t * op) /* device name and hi_lba may depend on id */ n = op->dev_names.size(); dev_name = op->dev_names[id % n]; - blk_sz = op->blk_szs[id % n]; + if (op->blk_szs.size() >= (unsigned)n) + blk_sz = op->blk_szs[id % n]; + else + blk_sz = DEF_LB_SZ; if ((UINT_MAX == op->hi_lba) && (n == (int)op->hi_lbas.size())) hi_lba = op->hi_lbas[id % n]; else @@ -1004,7 +1008,7 @@ work_thread(int id, struct opts_t * op) seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS; seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS; seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_TIME_IN_NS; - seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS; + seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS; if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) { pr2serr_lk("ioctl(EXTENDED(TIME_IN_NS)) failed, errno=%d %s\n", errno, strerror(errno)); @@ -1183,7 +1187,7 @@ work_thread(int id, struct opts_t * op) if (is_rw) { /* get new lb buffer or one from free list */ if (free_lst.empty()) { lbp = sg_memalign(op->lb_sz * op->num_lbs, 0, &free_lbp, - vb > 6); + false); if (NULL == lbp) { err = "out of memory"; break; @@ -1343,17 +1347,28 @@ work_thread(int id, struct opts_t * op) } } n = (op->wait_ms > 0) ? op->wait_ms : 0; - for (j = 0; (j < 1000000) && (0 == (res = poll(pfd, 1, n))); - ++j) - ; + if (n > 0) { + for (j = 0; (j < 1000000) && + (0 == (res = poll(pfd, 1, n))); + ++j) + ; + if (j >= 1000000) { + err = "poll() looped 1 million times"; + break; + } + if (res < 0) { + err = "poll(wait_ms) failed"; + break; + } + } else { + struct timespec ts; - if (j >= 1000000) { - err = "poll() looped 1 million times"; - break; - } - if (res < 0) { - err = "poll(wait_ms) failed"; - break; + ts.tv_sec = 0; + ts.tv_nsec = DEF_NANOSEC_WAIT; + if (nanosleep(&ts, NULL) < 0) { + err = "nanosleep() failed"; + break; + } } } } else { /* not full, not finished injecting */ @@ -1367,6 +1382,12 @@ work_thread(int id, struct opts_t * op) num_to_read = num_waiting_read > 0 ? num_waiting_read : 1; } else { + num_waiting_read = 0; + if (ioctl(sg_fd, SG_GET_NUM_WAITING, + &num_waiting_read) < 0) { + err = "ioctl(SG_GET_NUM_WAITING) failed"; + break; + } if (num_waiting_read > (op->ovn / 2)) num_to_read = num_waiting_read / 2; } @@ -1401,12 +1422,12 @@ work_thread(int id, struct opts_t * op) pack_id = -1; ask = pack_id; res = (op->v4) ? - finish_sg4_cmd(sg_fd, op->c2e, op->pack_id_force, pack_id, - op->submit, op->wait_ms, - thr_fin_eagain_count, nanosecs) : - finish_sg3_cmd(sg_fd, op->c2e, op->pack_id_force, pack_id, - op->submit, op->wait_ms, - thr_fin_eagain_count, nanosecs); + finish_sg4_cmd(sg_fd, op->c2e, pack_id, op->submit, + op->wait_ms, thr_fin_eagain_count, + nanosecs) : + finish_sg3_cmd(sg_fd, op->c2e, pack_id, op->submit, + op->wait_ms, thr_fin_eagain_count, + nanosecs); if (res) { err = "finish_sg3_cmd()"; if (ruip && (pack_id > 0)) { @@ -1420,13 +1441,14 @@ work_thread(int id, struct opts_t * op) } break; } - if (vb > 4) - pr2serr_lk("t_id=%d: finishing pack_id ask=%d, got=%d\n", id, - ask, pack_id); if (op->cmd_time && op->sg_vn_ge_30901) sum_nanosecs += nanosecs; ++thr_async_finishes; --num_outstanding; + if (vb > 4) + pr2serr_lk("t_id=%d: finishing pack_id ask=%d, got=%d, " + "outstanding=%d\n", id, ask, pack_id, + num_outstanding); auto p = pi2buff.find(pack_id); if (p == pi2buff.end()) { @@ -1684,7 +1706,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "34cdfghl:mM:n:NO:pq:Q:Rs:St:TuvVw:W", + c = getopt_long(argc, argv, "34cdfghl:L:mM:n:NO:pq:Q:Rs:St:TuvVw:W", long_options, &option_index); if (c == -1) break; @@ -1693,10 +1715,14 @@ main(int argc, char * argv[]) case '3': op->v3 = true; op->v3_given = true; + op->v4 = false; /* if '-4 -3' take latter */ + op->v4_given = false; break; case '4': op->v4 = true; op->v4_given = true; + op->v3 = false; + op->v3_given = false; break; case 'c': op->cmd_time = true; @@ -1741,6 +1767,15 @@ main(int argc, char * argv[]) return 1; } break; + case 'L': + op->lb_sz = sg_get_num(optarg); + if (op->lb_sz < 0) { + pr2serr_lk("--lbsz= expects power of 2\n"); + return 1; + } + if (0 == op->lb_sz) + op->lb_sz = DEF_LB_SZ; + break; case 'm': op->mmap_io = true; break; diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp index 4a8350a9..27438036 100644 --- a/testing/sgh_dd.cpp +++ b/testing/sgh_dd.cpp @@ -103,7 +103,7 @@ using namespace std; -static const char * version_str = "1.27 20190418"; +static const char * version_str = "1.28 20190419"; #ifdef __GNUC__ #ifndef __clang__ @@ -1028,7 +1028,7 @@ read_write_thread(void * v_tip) status = pthread_mutex_unlock(&clp->in_mutex); if (0 != status) err_exit(status, "unlock in_mutex"); if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) { - if (rep->debug > 1) + if (rep->debug > 2) pr2serr_lk("thread=%d: tail-end my_index>=dd_count, " "to_do=%u\n", rep->id, (uint32_t)def_arr.first.size()); @@ -1142,7 +1142,7 @@ skip_force_out_sequence: } if (0 == rep->num_blks) { if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) { - if (rep->debug > 1) + if (rep->debug > 2) pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id, (uint32_t)def_arr.first.size()); sgh_do_def_mrq(rep, def_arr); diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h index 053b0ffc..cea58f13 100644 --- a/testing/uapi_sg.h +++ b/testing/uapi_sg.h @@ -14,8 +14,8 @@ * Later extensions (versions 2, 3 and 4) to driver: * Copyright (C) 1998 - 2018 Douglas Gilbert * - * Version 4.0.08 (20190419) - * This version is for Linux 2.6, 3, 4 and 5 series kernels. + * Version 4.0.11 (20190427) + * This version is for Linux 4 and 5 series kernels. * * Documentation * ============= @@ -144,7 +144,10 @@ typedef struct sg_scsi_id { int scsi_type; /* TYPE_... defined in scsi/scsi.h */ short h_cmd_per_lun;/* host (adapter) maximum commands per lun */ short d_queue_depth;/* device (or adapter) maximum queue length */ - __u8 scsi_lun[8]; /* full 8 byte SCSI LUN [new v4 driver] */ + union { + int unused[2]; /* as per version 3 driver */ + __u8 scsi_lun[8]; /* full 8 byte SCSI LUN [in v4 driver] */ + }; } sg_scsi_id_t; /* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */ @@ -428,26 +431,34 @@ struct sg_header { #define SG_NEXT_CMD_LEN 0x2283 /* - * New ioctls to replace async write()/read() interface. Present in version - * 4 and later of the sg driver [>20181014]. These two ioctls accept both - * the sg_v3 interface (structure defined above) and the sg_v4 interface - * (structure defined in <include/uapi/linux/bsg.h> ). Following "read" and - * "write" terms are from the driver's POV, the _IO macros from users' POV. + * New ioctls to replace async (non-blocking) write()/read() interface. + * Present in version 4 and later of the sg driver [>20190427]. The + * SG_IOSUBMIT_V3 and SG_IORECEIVE_V3 ioctls accept the sg_v3 interface + * based on struct sg_io_hdr shown above. The SG_IOSUBMIT and SG_IORECEIVE + * ioctls accept the sg_v4 interface based on struct sg_io_v4 found in + * <include/uapi/linux/bsg.h>. These objects are passed by a pointer in + * the third argument of the ioctl. * - * SG_IOSUBMIT and SG_IORECEIVE can take a pointer to a v4 or v3 interface - * which have different lengths (v4 is longer) but their definitions below - * encode v4's length into the ioctl number. So users of the v3 interface - * would be best to place a v3 structure inside (overwriting and at the start - * of) a v4 structure and pass a pointer to that v4 structure to the ioctl. + * Data may be transferred both from the user space to the driver by these + * ioctls. Hence the _IOWR macro is used here to generate the ioctl number + * rather than _IOW or _IOR. */ -/* via pointer reads sg v3 or v4 object, optionally writes tag, so _IOWR */ +/* Submits a v4 interface object to driver, optionally receive tag back */ #define SG_IOSUBMIT _IOWR(SG_IOCTL_MAGIC_NUM, 0x41, struct sg_io_v4) -/* via pointer optionally reads tag, writes sg v3 or v4 object, so _IOWR */ + +/* Gives some v4 identifying info to driver, receives associated response */ #define SG_IORECEIVE _IOWR(SG_IOCTL_MAGIC_NUM, 0x42, struct sg_io_v4) -/* via pointer reads v4 object (including tag), writes nothing, so _IOW */ +/* Provides identifying info about a prior submission (e.g. a tag) */ #define SG_IOABORT _IOW(SG_IOCTL_MAGIC_NUM, 0x43, struct sg_io_v4) +/* Submits a v3 interface object to driver */ +#define SG_IOSUBMIT_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x45, struct sg_io_hdr) + +/* Gives some v3 identifying info to driver, receives associated response */ +#define SG_IORECEIVE_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x46, struct sg_io_hdr) + + /* command queuing is always on when the v3 or v4 interface is used */ #define SG_DEF_COMMAND_Q 0 |