sg_turs: estimated time-to-ready, add --delay=MS option; sg_requests: cleanup; sg_pt: add partial_clear_scsi_pt_obj, get_scsi_pt_cdb_len and get_scsi_pt_cdb_buf
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@857 6180dd3e-e324-4e3e-922d-17de1ae2f315
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index 54e0d23..1fd9133 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -60,14 +60,14 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.18 20200716";
+static const char * version_str = "Version: 1.18 20200719";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
#define SDIAG_CMD_LEN 6
#define SENSE_BUFFER_LEN 96
-#define EBUFF_SZ 256
+#define EBUFF_SZ 512
#ifndef SG_FLAG_Q_AT_TAIL
#define SG_FLAG_Q_AT_TAIL 0x10
@@ -105,6 +105,9 @@
static int reserve_buff_sz = DEF_RESERVE_BUFF_SZ;
static int num_mrqs = 0;
static int num_sgnw = 0;
+static int dname_current = 0;
+static int dname_last = 0;
+static int dname_pos = 0;
static int verbose = 0;
static const char * relative_cp = NULL;
@@ -119,16 +122,18 @@
" [-m=MRQS[,I|S]] [-M] [-n] [-o] [-r=SZ] "
"[-s=SEC]\n"
" [-S] [-t] [-T=NUM] [-v] [-V] [-w]\n"
- " <sg_device> [<sg_device2>]\n"
+ " <sg_device>[-<num>] [<sg_device2>]\n"
" where:\n"
+ " -3 use sg v3 interface (def: sg v4 if available)\n"
" -c timestamp when sg driver created <sg_device>\n"
" -f fork and test share between processes\n"
" -h help: print usage message then exit\n"
" -I=0|1 iterator test of mid-level; 0: unlocked, 1: "
"locked\n"
" does test -T=NUM times, outputs duration\n"
- " -J=0|1 object walk (to root); 0: without ptr; 1: with "
- "ptr\n"
+ " -J=0|1 object walk up then 2 lookups; 0: no logging; "
+ "1: log\n"
+ " up-scan once per 1000 iterations\n"
" -l=Q_LEN queue length, between 1 and 511 (def: 16)\n"
" -m=MRQS[,I|S] test multi-req, MRQS number to do; if "
"the letter\n"
@@ -151,7 +156,14 @@
" ioctl(SG_GET_NUM_WAITING); then exit\n"
" -v increase verbosity of output\n"
" -V print version string then exit\n"
- " -w write (submit) only then exit\n");
+ " -w write (submit) only then exit\n\n");
+ printf("There are various groups of options for different tests. The "
+ "get_num_waiting\ngroup needs '-T=NUM' given. When '-I=0|1' is "
+ "also given then an object tree\niterator test is done NUM "
+ "times. If instead '-J=0|1' is given then an\nobject tree "
+ "traversal (up/down) is done 10,000 times (and NUM is\n"
+ "ignored).\n"
+ );
}
static void
@@ -756,10 +768,13 @@
int
main(int argc, char * argv[])
{
- bool done;
+ bool done, is_first;
bool nw_given = false;
- int sg_fd, k, ok, pack_id, num_waiting;
+ bool has_dname_range = false;
+ int k, ok, pack_id, num_waiting;
int res = 0;
+ int sum_nw = 0;
+ int sg_fd = -1;
int sg_fd2 = -1;
int sock = -1;
uint8_t inq_cdb[INQ_CMD_LEN] =
@@ -770,9 +785,11 @@
sg_io_hdr_t io_hdr[MAX_Q_LEN];
sg_io_hdr_t rio_hdr;
char ebuff[EBUFF_SZ];
+ char dname[256];
uint8_t sense_buffer[MAX_Q_LEN][SENSE_BUFFER_LEN];
const char * second_fname = NULL;
const char * cp;
+ char * chp;
struct sg_scsi_id ssi;
@@ -900,7 +917,7 @@
break;
}
}
- if (iterator_test >= 0)
+ if ((iterator_test >= 0) || (object_walk_test >= 0))
nw_given = false;
if (show_size_value) {
@@ -953,58 +970,87 @@
usage();
return 1;
}
+ memset(dname, 0, sizeof(dname));
+ if (strlen(file_name) > 255) {
+ fprintf(stderr, "file_name too long\n");
+ goto out;
+ }
+ strncpy(dname, file_name, sizeof(dname) - 1);
+ if ((chp = strchr(dname, '-'))) {
+ if (1 != sscanf(chp + 1, "%d", &dname_last)) {
+ fprintf(stderr, "can't code number after '-' in file_name\n");
+ goto out;
+ }
+ *chp = '\0';
+ --chp;
+ while (isdigit(*chp))
+ --chp;
+ ++chp;
+ if (1 != sscanf(chp, "%d", &dname_current)) {
+ fprintf(stderr, "can't code number before '-' in file_name\n");
+ goto out;
+ }
+ *chp = '\0';
+ has_dname_range = true;
+ dname_pos = strlen(dname);
+ }
+ is_first = true;
+
+dname_range_loop:
+ if (has_dname_range)
+ sprintf(dname + dname_pos, "%d", dname_current);
/* An access mode of O_RDWR is required for write()/read() interface */
- if ((sg_fd = open(file_name, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "error opening file: %s", file_name);
+ if ((sg_fd = open(dname, O_RDWR)) < 0) {
+ snprintf(ebuff, EBUFF_SZ, "error opening file: %s", dname);
perror(ebuff);
return 1;
}
if (verbose)
fprintf(stderr, "opened given file: %s successfully, fd=%d\n",
- file_name, sg_fd);
+ dname, sg_fd);
if (ioctl(sg_fd, SG_GET_VERSION_NUM, &sg_drv_ver_num) < 0) {
pr2serr("ioctl(SG_GET_VERSION_NUM) failed, errno=%d %s\n", errno,
strerror(errno));
goto out;
}
- printf("Linux sg driver version: %d\n", sg_drv_ver_num);
-
- if (object_walk_test >= 0) {
- k = (object_walk_test == 0) ? -999 : 999;
- if (ioctl(sg_fd, SG_SET_DEBUG, &k) < 0) {
- res = errno;
- fprintf(stderr, "%s%d: ioctl(SG_SET_DEBUG) failed errno=%d\n",
- relative_cp, k, res);
- }
- goto out;
- }
+ if (is_first)
+ printf("Linux sg driver version: %d\n", sg_drv_ver_num);
if (create_time && (sg_drv_ver_num > 40030)) {
- pr_create_dev_time(sg_fd, file_name);
+ pr_create_dev_time(sg_fd, dname);
goto out;
}
- if (nw_given || (iterator_test >= 0)) { /* -T=NUM and/or -I=0|1 */
+ if (nw_given || (iterator_test >= 0) || (object_walk_test >= 0)) {
+ /* -T=NUM and/or -I=0|1 or -j=0|1 */
/* time ioctl(SG_GET_NUM_WAITING) or do iterator_test */
- int nw, sum_nw;
+ int nw;
struct timespec start_tm, fin_tm, res_tm;
- if (nw_given)
- printf("Timing %d calls to ioctl(SG_GET_NUM_WAITING)\n",
- num_sgnw);
- else
- printf("Timing calls to ioctl(SG_SET_DEBUG, %d)\n",
- num_sgnw);
- if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
- res = errno;
- perror("start clock_gettime() failed:");
- goto out;
+ if (is_first) {
+ int rang = has_dname_range ? (1 + dname_last - dname_current) : 1;
+
+ is_first = false;
+ if (nw_given)
+ printf("Timing %dx%d calls to ioctl(SG_GET_NUM_WAITING)\n",
+ rang, num_sgnw);
+ else if (iterator_test >= 0) {
+ k = num_sgnw + 1000;
+ printf("Timing %d calls to ioctl(SG_SET_DEBUG, %d)\n",
+ rang, ((0 == iterator_test) ? -k : k));
+ } else
+ printf("Timing %d calls to ioctl(SG_SET_DEBUG, %d)\n",
+ rang, (object_walk_test == 0) ? 999 : -999);
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
+ res = errno;
+ perror("start clock_gettime() failed:");
+ goto out;
+ }
}
if (nw_given) {
- for (k = 0, sum_nw = 0; k < num_sgnw; ++k, sum_nw += nw) {
+ for (k = 0; k < num_sgnw; ++k, sum_nw += nw) {
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &nw) < 0) {
res = errno;
fprintf(stderr, "%d: ioctl(SG_GET_NUM_WAITING) failed "
@@ -1012,7 +1058,7 @@
goto out;
}
}
- } else {
+ } else if (iterator_test >= 0) {
int fd, pid;
k = num_sgnw + 1000;
@@ -1049,6 +1095,31 @@
fprintf(stderr, "%s%d: ioctl(SG_SET_DEBUG) failed errno=%d\n",
relative_cp, k, res);
goto out;
+ } else if (verbose)
+ fprintf(stderr, "%siterator_test good ioctl(SG_SET_DEBUG, "
+ "%d)\n", relative_cp, k);
+ sum_nw += num_sgnw;
+ } else if (object_walk_test >= 0) {
+ const char * ccp = "object_walk_test";
+
+ relative_cp = "";
+ k = (object_walk_test == 0) ? 999 : -999;
+ if (ioctl(sg_fd, SG_SET_DEBUG, &k) < 0) {
+ res = errno;
+ fprintf(stderr, "%s: ioctl(SG_SET_DEBUG, %d) failed "
+ "errno=%d\n", ccp, k, res);
+ } else if (verbose)
+ fprintf(stderr, "%s: good call to ioctl(SG_SET_DEBUG, %d)\n",
+ ccp, k);
+ sum_nw += 10000; /* (1_up-scan + 2_lookups) * 10,000 times */
+ }
+
+ if (has_dname_range) {
+ ++dname_current;
+ if (dname_current <= dname_last) {
+ if (sg_fd >= 0)
+ close(sg_fd);
+ goto dname_range_loop;
}
}
if (0 != clock_gettime(CLOCK_MONOTONIC, &fin_tm)) {
@@ -1076,7 +1147,7 @@
if (m > 0.000001)
printf("%sCalls per second: %.2f\n", relative_cp,
- (double)num_sgnw / m);
+ (double)sum_nw / m);
}
res = 0;
goto out;
@@ -1133,7 +1204,7 @@
cp = do_fork ? relative_cp : "";
if (! do_v3_only) {
- if (tst_extended_ioctl(file_name, sg_fd, second_fname, sg_fd2, sock,
+ if (tst_extended_ioctl(dname, sg_fd, second_fname, sg_fd2, sock,
cp))
goto out;
}