aboutsummaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-29 07:13:59 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-29 07:13:59 +0000
commitc3da9a6b41cbae7940180645721a35becdd5bc99 (patch)
tree6704c41130a47d9b3bd9df2920dab9626f8754c1 /testing
parent7dff7ae9433763457872082271aac0487e14d158 (diff)
downloadsg3_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.cpp153
-rw-r--r--testing/sgh_dd.cpp6
-rw-r--r--testing/uapi_sg.h43
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