aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-11 00:23:23 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-11 00:23:23 +0000
commitcc730c8de77b8f35d924cb4a01437f7166d85e12 (patch)
tree8059ed69638442a4ba2df26baf65044d78448c3b
parent3905f5ce447048fdc0fe1f9573cab87df97972bb (diff)
downloadsg3_utils-cc730c8de77b8f35d924cb4a01437f7166d85e12.tar.gz
sg_modes+sg_logs: placeholders for Commmand duration limits pages (sbc4r17 for spc6r?)
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@817 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog6
-rw-r--r--README26
-rw-r--r--doc/sg3_utils.84
-rw-r--r--src/sg_logs.c11
-rw-r--r--src/sg_modes.c6
-rw-r--r--testing/Makefile.cplus35
-rw-r--r--testing/sg_tst_async.cpp146
-rw-r--r--testing/sg_tst_ioctl.c14
-rw-r--r--testing/uapi_sg.h5
9 files changed, 189 insertions, 64 deletions
diff --git a/ChangeLog b/ChangeLog
index d657df4b..4350f984 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.45 [20190403] [svn: r816]
+Changelog for sg3_utils-1.45 [20190410] [svn: r817]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (spc5r20)
@@ -15,6 +15,10 @@ Changelog for sg3_utils-1.45 [20190403] [svn: r816]
- sg_xcopy: add --fco (fast copy only) (spc5r20)
- implement --app=1 (append) on regular OFILE type
- sg_scan (win32): expand limits for big arrays
+ - sg_modes: placeholders for Command duration limit
+ T2A and T2B mpages (sbc4r17)
+ - sg_logs: placeholder for Commmand duration limits
+ statistics lpage (sbc4r17)
- sg_lib: add sg_t10_uuid_desig2str()
- tweak sg_pt interface to better handle bidi
- sg_cmds_process_resp(): two arguments removed
diff --git a/README b/README
index 8a741e3f..99c02400 100644
--- a/README
+++ b/README
@@ -203,7 +203,7 @@ and disable the creation of the shared library (libsgutils<num>.so) this
invocation could be used: "./configure --prefix=/usr --disable-shared".
To reduce the size of an executable as well try this:
"./configure --prefix=/usr --disable-shared --disable-scsistrings".
-Also --disable-shared will produce (realtively) "static" executables in
+Also --disable-shared will produce (relatively) "static" executables in
the src directory that are easier to debug. And
"./configure --enable-debug" will compile with more debug type options,
including more compiler checks and defining "DEBUG" within the src and
@@ -399,6 +399,28 @@ queue limit of 16). Multiple threads doing the same thing act as a
multiplier to that queue limit.
+NVME Support
+============
+Firstly the author has no intention of extending this package to contain
+general purpose NVMe utilities. That leaves the areas where SCSI overlaps
+with NVMe. There was a SCSI to NVMe Translation Layer (SNTL) driver in the
+Linux kernel based on a white paper from NVM Express. Intel has withdrawn
+that driver and T10 (SCSI) and NVM Express have made no further attempts
+to standardize a SNTL. Given the SCSI to ATA Translation Layer (SATL) which
+is standardized by T10, it is pretty clear what a SNTL should do.
+
+The NVMe Management Interface (NVME-MI) committee have decided to use SES-3
+standard from T10 via the newly added SES Send and SES Receive MI commands.
+So the sg_ses utility and this package's library have been extended to use
+these commands when a NVMe device (typically a disk enclosure) is detected.
+This has been tested by a disk vendor who is happy with the results. Other
+user reports are welcome as the author does not have equipment to test
+this.
+
+Other utilities in this package that use the SES Send and Receive commands,
+or the SNTL in the library are sg_senddiag, sg_inq and sg_readcap.
+
+
Command line processing
=======================
These utilities can be divided into 3 groups when their handling of command
@@ -519,4 +541,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-28th June 2018
+10th April 2019
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index 836e1769..e2d3f9d7 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "February 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG3_UTILS "8" "April 2019" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -35,7 +35,7 @@ Architecture Model (SAM) with SAM\-5 being the most recent standard (ANSI
INCITS 515\-2016) with the most recent draft being SAM\-6 revision 4 . SCSI
commands in common with all device types can be found in SCSI Primary
Commands (SPC) of which SPC\-4 is the most recent standard (ANSI INCITS
-513-2015). The most recent SPC draft is SPC\-5 revision 19. Block device
+513-2015). The most recent SPC draft is SPC\-5 revision 21. Block device
specific commands (e.g. as used by disks) are in SBC, those for tape drives
in SSC, those for SCSI enclosures in SES and those for CD/DVD/BD drives in
MMC.
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 25088b45..ed246674 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -36,7 +36,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.72 20190203"; /* spc5r20 + sbc4r16 */
+static const char * version_str = "1.73 20190405"; /* spc5r21 + sbc4r17 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -70,6 +70,7 @@ static const char * version_str = "1.72 20190203"; /* spc5r20 + sbc4r16 */
#define PENDING_DEFECTS_SUBPG 0x1 /* page 0x15 */
#define BACKGROUND_OP_SUBPG 0x2 /* page 0x15 */
#define CACHE_STATS_SUBPG 0x20 /* page 0x19 */
+#define CMD_DUR_LIMITS_SUBPG 0x21 /* page 0x19, spc6 */
#define ENV_REPORTING_SUBPG 0x1 /* page 0xd */
#define UTILIZATION_SUBPG 0x1 /* page 0xe */
#define ENV_LIMITS_SUBPG 0x2 /* page 0xd */
@@ -403,8 +404,10 @@ static struct log_elem log_arr[] = {
"gsp", show_stats_perform_pages}, /* 0x19, 0x0 */
{STATS_LPAGE, 0x1, 0x1f, -1, MVP_STD, "Group Statistics and Performance",
"grsp", show_stats_perform_pages}, /* 0x19, 0x1...0x1f */
- {STATS_LPAGE, 0x20, 0, -1, MVP_STD, "Cache memory statistics", "cms",
- show_cache_stats_page}, /* 0x19, 0x20 */
+ {STATS_LPAGE, CACHE_STATS_SUBPG, 0, -1, MVP_STD, /* 0x19, 0x20 */
+ "Cache memory statistics", "cms", show_cache_stats_page},
+ {STATS_LPAGE, CMD_DUR_LIMITS_SUBPG, 0, -1, MVP_STD, /* 0x19, 0x21 */
+ "Commmand duration limits statistics", "cdl", NULL /* spc6r? */ },
{PCT_LPAGE, 0, 0, -1, MVP_STD, "Power condition transitions", "pct",
show_power_condition_transitions_page}, /* 0x1a, 0 */
{0x1b, 0, 0, PDT_TAPE, MVP_STD, "Data compression", "dc",
@@ -6764,7 +6767,7 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op)
spf = !!(resp[0] & 0x40);
pg_code = resp[0] & 0x3f;
if ((VP_HITA == op->vend_prod_num) && (pg_code >= 0x30))
- subpg_code = resp[1]; /* Hitachi don't set SPF on VS pages */
+ subpg_code = resp[1]; /* Hitachi don't set SPF on VS pages */
else
subpg_code = spf ? resp[1] : 0;
op->decod_subpg_code = subpg_code;
diff --git a/src/sg_modes.c b/src/sg_modes.c
index ee0378e4..17617cfb 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2018 D. Gilbert
+ * Copyright (C) 2000-2019 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.67 20181203";
+static const char * version_str = "1.68 20190405";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -118,6 +118,8 @@ static struct page_code_desc pc_desc_common[] = {
{0xa, 0x1, "coe", "Control extension"},
{0xa, 0x3, "cdla", "Command duration limit A"},
{0xa, 0x4, "cdlb", "Command duration limit B"},
+ {0xa, 0x7, "cdt2a", "Command duration limit T2A"}, /* spc6r? */
+ {0xa, 0x8, "cdt2b", "Command duration limit T2B"}, /* spc6r? */
{0x15, 0x0, "ext_", "Extended"},
{0x16, 0x0, "edts", "Extended device-type specific"},
{0x18, 0x0, "pslu", "Protocol specific lu"},
diff --git a/testing/Makefile.cplus b/testing/Makefile.cplus
index 51a5bad7..052e815e 100644
--- a/testing/Makefile.cplus
+++ b/testing/Makefile.cplus
@@ -4,10 +4,10 @@ PREFIX=/usr/local
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
MANDIR=$(DESTDIR)/$(PREFIX)/man
-## CC = g++
-## LD = g++
-CXX = clang++-7
-LD = clang++-7
+## CXX = g++
+## CXX = clang++
+## CXX = clang++-7
+CXXLD = $(CXX)
EXECS = sg_tst_excl sg_tst_excl2 sg_tst_excl3 sg_tst_context sg_tst_async \
sgh_dd
@@ -22,13 +22,16 @@ MAN_PREF = man8
LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-CPPFLAGS = -std=c++11 -pthread -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
-# CPPFLAGS = -std=c++11 -pthread -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS) -DDEBUG
-## CFLAGS = -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -iquote ../include -D_REENTRANT -DSG_KERNEL_INCLUDES $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -pedantic -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
+CXXFLAGS = -std=c++17 -pthread -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
+# CXXFLAGS = -std=c++11 -pthread -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
+# CXXFLAGS = -std=c++11 -pthread -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS) -DDEBUG
+## CXXFLAGS = -g -O2 -W -Wall -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
+# CXXFLAGS = -g -O2 -Wall -iquote ../include -D_REENTRANT -DSG_KERNEL_INCLUDES $(LARGE_FILE_FLAGS)
+# CXXFLAGS = -g -O2 -Wall -pedantic -iquote ../include -D_REENTRANT $(LARGE_FILE_FLAGS)
-LDFLAGS = -std=c++11 -pthread
+LDFLAGS = -std=c++17 -pthread
+# LDFLAGS = -std=c++11 -pthread
+# LDFLAGS = -pthread
LIBFILESOLD = ../lib/sg_lib.o ../lib/sg_lib_data.o ../lib/sg_io_linux.o
LIBFILESNEW = ../lib/sg_pt_linux_nvme.o ../lib/sg_lib.o ../lib/sg_lib_data.o \
@@ -49,22 +52,22 @@ clean:
/bin/rm -f *.o $(EXECS) $(EXTRAS) $(BSG_EXTRAS) core .depend
sg_tst_excl: sg_tst_excl.o $(LIBFILESOLD)
- $(LD) -o $@ $(LDFLAGS) $^
+ $(CXXLD) -o $@ $(LDFLAGS) $^
sg_tst_excl2: sg_tst_excl2.o $(LIBFILESNEW)
- $(LD) -o $@ $(LDFLAGS) $^
+ $(CXXLD) -o $@ $(LDFLAGS) $^
sg_tst_excl3: sg_tst_excl3.o $(LIBFILESNEW)
- $(LD) -o $@ $(LDFLAGS) $^
+ $(CXXLD) -o $@ $(LDFLAGS) $^
sg_tst_context: sg_tst_context.o $(LIBFILESNEW)
- $(LD) -o $@ $(LDFLAGS) $^
+ $(CXXLD) -o $@ $(LDFLAGS) $^
sg_tst_async: sg_tst_async.o $(LIBFILESNEW)
- $(LD) -o $@ $(LDFLAGS) $^
+ $(CXXLD) -o $@ $(LDFLAGS) $^
sgh_dd: sgh_dd.o $(LIBFILESNEW)
- $(LD) -o $@ $(LDFLAGS) -pthread $^
+ $(CXXLD) -o $@ $(LDFLAGS) -pthread $^
install: $(EXECS)
install -d $(INSTDIR)
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp
index cc4e9bba..bdd024fb 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.26 20190403";
+static const char * version_str = "1.26 20190409";
static const char * util_name = "sg_tst_async";
/* This is a test program for checking the async usage of the Linux sg
@@ -143,7 +143,7 @@ using namespace std::chrono;
#define DEF_LBA 1000
#define MAX_Q_PER_FD 16383 /* sg driver per file descriptor limit */
-#define MAX_CONSEC_NOMEMS 4 /* was 16 */
+#define MAX_CONSEC_NOMEMS 4 /* was 16 */
#define URANDOM_DEV "/dev/urandom"
#ifndef SG_FLAG_Q_AT_TAIL
@@ -184,6 +184,7 @@ enum myQDiscipline {MYQD_LOW, /* favour completions over new cmds */
struct opts_t {
vector<const char *> dev_names;
+ vector<int> blk_szs;
bool block;
bool cmd_time;
bool direct;
@@ -194,7 +195,10 @@ struct opts_t {
bool sg_vn_ge_30901;
bool submit;
bool verbose_given;
+ bool v3;
+ bool v3_given;
bool v4;
+ bool v4_given;
bool version_given;
int maxq_per_thread;
int num_per_thread;
@@ -203,12 +207,13 @@ struct opts_t {
vector<unsigned int> hi_lbas; /* only used when hi_lba=-1 */
int lb_sz;
int num_lbs;
+ int ovn; /* override number for submission */
int stats;
int verbose;
int wait_ms;
command2execute c2e;
- blkLQDiscipline blqd;
- myQDiscipline myqd;
+ blkLQDiscipline blqd; /* --qat= 0|1 -> at_head|at_tail */
+ myQDiscipline myqd; /* --qfav= value (def: 2 --> MYQD_HIGH) */
};
static struct opts_t a_opts;
@@ -254,6 +259,7 @@ private:
};
static struct option long_options[] = {
+ {"v3", no_argument, 0, '3'},
{"v4", no_argument, 0, '4'},
{"cmd-time", no_argument, 0, 'c'},
{"cmd_time", no_argument, 0, 'c'},
@@ -270,6 +276,7 @@ static struct option long_options[] = {
{"num-pt", required_argument, 0, 'n'},
{"num_pt", required_argument, 0, 'n'},
{"noxfer", no_argument, 0, 'N'},
+ {"override", required_argument, 0, 'O'},
{"pack-id", no_argument, 0, 'p'},
{"pack_id", no_argument, 0, 'p'},
{"qat", required_argument, 0, 'q'},
@@ -294,12 +301,13 @@ usage(void)
printf("Usage: %s [--cmd-time] [--direct] [--force] [--generic-sync]\n"
" [--help] [--lba=LBA+] [--maxqpt=QPT] "
"[--mmap-io]\n"
- " [--numpt=NPT] [--noxfer] [--pack-id] "
- "[--qat=AT]\n"
- " [-qfav=FAV] [--read] [--stats] [--submit]\n"
+ " [--numpt=NPT] [--noxfer] [--override=OVN] "
+ "[--pack-id]\n"
+ " [--qat=AT] [-qfav=FAV] [--read] [--stats] "
+ "[--submit]\n"
" [--szlb=LB[,NLBS]] [--tnum=NT] [--tur] "
- "[--v4]\n"
- " [--verbose] [--version] [--wait=MS] "
+ "[--v3]\n"
+ " [--v4] [--verbose] [--version] [--wait=MS] "
"[--write]\n"
" <sg_disk_device>*\n",
util_name);
@@ -328,9 +336,13 @@ usage(void)
"(def: %d)\n", DEF_NUM_PER_THREAD);
printf(" --noxfer|-N no data xfer (def: xfer on READ and "
"WRITE)\n");
+ printf(" --override OVN|-O OVN override FAV=2 when OVN queue "
+ "depth\n"
+ " reached (def: 0 -> no override)\n");
printf(" --pack-id|-p set FORCE_PACK_ID, pack-id input to "
"read/finish\n");
- printf(" --qat=AT|-q AT AT=0: q_at_head; AT=1: q_at_tail\n");
+ printf(" --qat=AT|-q AT AT=0: q_at_head; AT=1: q_at_tail (def: "
+ "(drv): head)\n");
printf(" --qfav=FAV|-Q FAV FAV=0: favour completions (smaller q),\n"
" FAV=1: medium,\n"
" FAV=2: favour submissions (larger q, "
@@ -345,8 +357,10 @@ usage(void)
printf(" --tnum=NT|-t NT number of threads (def: %d)\n",
DEF_NUM_THREADS);
printf(" --tur|-T do TEST UNIT READYs (default is TURs)\n");
- printf(" --v4|-4 use sg v4 interface (def: v3). If given "
- "sets --submit\n");
+ printf(" --v3|-3 use sg v3 interface (def: v3 if driver < "
+ "3.9)\n");
+ printf(" --v4|-4 use sg v4 interface (def if v4 driver). Sets "
+ "--submit\n");
printf(" --verbose|-v increase verbosity\n");
printf(" --version|-V print version number then exit\n");
printf(" --wait=MS|-w MS >0: poll(<wait_ms>); =0: poll(0); (def: "
@@ -417,9 +431,9 @@ get_urandom_uint(void)
}
#define TUR_CMD_LEN 6
-#define READ16_REPLY_LEN 512
#define READ16_CMD_LEN 16
-#define WRITE16_REPLY_LEN 512
+#define READ16_REPLY_LEN 4096
+#define WRITE16_REPLY_LEN 4096
#define WRITE16_CMD_LEN 16
/* Returns 0 if command injected okay, return -1 for error and 2 for
@@ -487,7 +501,7 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba,
for (int k = 0;
(submit ? ioctl(sg_fd, SG_IOSUBMIT, ptp) :
- write(sg_fd, ptp, sizeof(*ptp)) < 0);
+ write(sg_fd, ptp, sizeof(*ptp)) < 0);
++k) {
if ((ENOMEM == errno) && (k < MAX_CONSEC_NOMEMS)) {
this_thread::yield();
@@ -909,10 +923,11 @@ work_thread(int id, struct opts_t * op)
int open_flags = O_RDWR;
int thr_async_starts = 0;
int thr_async_finishes = 0;
+ int thr_ovn_force_read = 0;
int vb = op->verbose;
int k, n, res, sg_fd, num_outstanding, do_inc, npt, pack_id, sg_flags;
int num_waiting_read, num_to_read, sz, ern, encore_pack_id, ask, j, m, o;
- int prev_pack_id;
+ int prev_pack_id, blk_sz;
unsigned int thr_start_eagain_count = 0;
unsigned int thr_start_ebusy_count = 0;
unsigned int thr_start_e2big_count = 0;
@@ -940,6 +955,7 @@ 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 ((UINT_MAX == op->hi_lba) && (n == (int)op->hi_lbas.size()))
hi_lba = op->hi_lbas[id % n];
else
@@ -1078,7 +1094,8 @@ work_thread(int id, struct opts_t * op)
else {
++m;
if (m > 100) {
- pr2serr_lk("%d->id: m=%d\n", id, m);
+ if (vb)
+ pr2serr_lk("%d->id: no main loop inc =%d times\n", id, m);
m = 0;
}
}
@@ -1206,11 +1223,11 @@ work_thread(int id, struct opts_t * op)
pr2serr_lk("t_id=%d: starting pack_id=%d\n", id, pack_id);
res = (op->v4) ?
start_sg4_cmd(sg_fd, op->c2e, pack_id, lba, lbp,
- op->lb_sz * op->num_lbs, sg_flags, op->submit,
+ blk_sz * op->num_lbs, sg_flags, op->submit,
thr_start_eagain_count, thr_start_ebusy_count,
thr_start_e2big_count, thr_start_edom_count) :
start_sg3_cmd(sg_fd, op->c2e, pack_id, lba, lbp,
- op->lb_sz * op->num_lbs, sg_flags, op->submit,
+ blk_sz * op->num_lbs, sg_flags, op->submit,
thr_start_eagain_count, thr_start_ebusy_count,
thr_start_e2big_count, thr_start_edom_count);
if (res) {
@@ -1290,6 +1307,22 @@ work_thread(int id, struct opts_t * op)
break;
case MYQD_HIGH:
default:
+ if (op->ovn > 0) {
+ if (op->sg_vn_ge_30901) {
+ int num_subm = num_submitted(sg_fd);
+
+ if (num_subm > op->ovn) {
+ num_to_read = num_waiting_read > 0 ?
+ num_waiting_read : 1;
+ break;
+ }
+ } else {
+ if (num_waiting_read > (op->ovn / 2)) {
+ num_to_read = num_waiting_read / 2;
+ break;
+ }
+ }
+ }
num_to_read = 1;
break;
}
@@ -1321,9 +1354,21 @@ work_thread(int id, struct opts_t * op)
}
}
} else { /* not full, not finished injecting */
- if (MYQD_HIGH == op->myqd)
+ if (MYQD_HIGH == op->myqd) {
num_to_read = 0;
- else {
+ if (op->ovn) {
+ if (op->sg_vn_ge_30901) {
+ int num_subm = num_submitted(sg_fd);
+
+ if (num_subm > op->ovn)
+ num_to_read = num_waiting_read > 0 ?
+ num_waiting_read : 1;
+ } else {
+ if (num_waiting_read > (op->ovn / 2))
+ num_to_read = num_waiting_read / 2;
+ }
+ }
+ } else {
num_waiting_read = 0;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting_read) < 0) {
err = "ioctl(SG_GET_NUM_WAITING) failed";
@@ -1342,7 +1387,7 @@ work_thread(int id, struct opts_t * op)
pr2serr_lk("%d->id: num_to_read=%d\n", id, num_to_read);
}
while (num_to_read > 0) {
- --num_to_read;
+ --num_to_read;
if (op->pack_id_force) {
j = pi2buff.size();
if (j > 0)
@@ -1411,7 +1456,7 @@ work_thread(int id, struct opts_t * op)
} /* end of for loop over npt (number per thread) */
if (vb)
pr2serr_lk("%d->id: leaving main thread loop; k=%d, o=%d\n", id, k,
- o);
+ o);
close(sg_fd); // sg driver will handle any commands "in flight"
if (ruip)
delete ruip;
@@ -1441,8 +1486,11 @@ work_thread(int id, struct opts_t * op)
}
}
if ((vb > 2) && (k > 0))
- pr2serr_lk("t_id=%d Maximum number of READ/WRITEs queued: %d\n",
+ pr2serr_lk("%d->id: Maximum number of READ/WRITEs queued: %d\n",
id, k);
+ if (vb && (thr_ovn_force_read > 0))
+ pr2serr_lk("%d->id: Number of ovn (override number) forced reads: "
+ "%d\n", id, thr_ovn_force_read);
async_starts += thr_async_starts;
async_finishes += thr_async_finishes;
start_eagain_count += thr_start_eagain_count;
@@ -1536,6 +1584,7 @@ do_inquiry_prod_id(const char * dev_name, int block, int & sg_ver_num,
ret = 0;
} else
ret = -1;
+
close(sg_fd);
return ret;
}
@@ -1632,14 +1681,19 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "4cdfghl:mM:n:Npq:Q:Rs:St:TuvVw:W",
+ c = getopt_long(argc, argv, "34cdfghl:mM:n:NO:pq:Q:Rs:St:TuvVw:W",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
+ case '3':
+ op->v3 = true;
+ op->v3_given = true;
+ break;
case '4':
op->v4 = true;
+ op->v4_given = true;
break;
case 'c':
op->cmd_time = true;
@@ -1713,6 +1767,18 @@ main(int argc, char * argv[])
case 'N':
op->no_xfer = true;
break;
+ case 'O':
+ if (isdigit(*optarg))
+ op->ovn = sg_get_num(optarg);
+ else {
+ pr2serr_lk("--override= expects a number\n");
+ return 1;
+ }
+ if (op->ovn < 0) {
+ pr2serr_lk("--override= bad number\n");
+ return 1;
+ }
+ break;
case 'p':
op->pack_id_force = true;
break;
@@ -1849,7 +1915,12 @@ main(int argc, char * argv[])
} else
op->maxq_per_thread = 1;
}
-
+ if (! op->cmd_time && getenv("SG3_UTILS_LINUX_NANO")) {
+ op->cmd_time = true;
+ if (op->verbose)
+ fprintf(stderr, "setting nanosecond timing due to environment "
+ "variable: SG3_UTILS_LINUX_NANO\n");
+ }
if (0 == op->dev_names.size()) {
fprintf(stderr, "No sg_disk_device-s given\n\n");
usage();
@@ -1907,8 +1978,20 @@ main(int argc, char * argv[])
if (sg_ver_num < 30000) {
pr2serr_lk("%s either not sg device or too old\n", dev_name);
return 2;
- } else if (sg_ver_num >= 30901)
+ } else if (sg_ver_num >= 30901) {
op->sg_vn_ge_30901 = true;
+ if (! (op->v3_given || op->v4_given)) {
+ op->v4 = true;
+ op->v3 = false;
+ op->submit = true;
+ }
+ } else {
+ if (! (op->v3_given || op->v4_given)) {
+ op->v4 = false;
+ op->v3 = true;
+ op->submit = false;
+ }
+ }
if ((SCSI_WRITE16 == op->c2e) || (SCSI_READ16 == op->c2e)) {
res = do_read_capacity(dev_name, op->block, &last_lba,
@@ -1924,14 +2007,9 @@ main(int argc, char * argv[])
pr2serr_lk(">>> Logical block size (%d) of %s\n"
" differs from command line option (or "
"default)\n", blk_sz, dev_name);
- if (force)
- pr2serr_lk("Ignoring due to --force option\n");
- else {
- pr2serr_lk("Exiting due to block size discrepancy, "
- "use --force to override\n");
- return 1;
- }
+ pr2serr_lk("... continue anyway\n");
}
+ op->blk_szs.push_back(blk_sz);
if (UINT_MAX == op->hi_lba)
op->hi_lbas.push_back(last_lba);
}
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index 08c8bab1..fb21bcb2 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -56,7 +56,7 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.07 20190402";
+static const char * version_str = "Version: 1.08 20190406";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
@@ -393,6 +393,18 @@ tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
printf(" %sread_value[SG_SEIRV_SUBMITTED]= %u\n", cp, seip->read_value);
memset(seip, 0, sizeof(*seip));
+ seip->sei_wr_mask |= SG_SEIM_READ_VAL;
+ seip->sei_rd_mask |= SG_SEIM_READ_VAL;
+ seip->read_value = SG_SEIRV_DEV_SUBMITTED;
+ if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
+ pr2serr("ioctl(SG_SET_GET_EXTENDED) failed, errno=%d %s\n", errno,
+ strerror(errno));
+ return 1;
+ }
+ printf(" %sread_value[SG_SEIRV_DEV_SUBMITTED]= %u\n", cp,
+ seip->read_value);
+
+ memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
seip->sei_rd_mask |= SG_SEIM_SHARE_FD;
#if 1
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index 635bb587..ad41d679 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -14,7 +14,7 @@
* Later extensions (versions 2, 3 and 4) to driver:
* Copyright (C) 1998 - 2018 Douglas Gilbert
*
- * Version 4.0.07 (20190320)
+ * Version 4.0.08 (20190406)
* This version is for Linux 2.6, 3, 4 and 5 series kernels.
*
* Documentation
@@ -205,10 +205,11 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
#define SG_SEIRV_BOOL_MASK 0x1 /* get SG_CTL_FLAGM_ALL_BITS */
#define SG_SEIRV_VERS_NUM 0x2 /* get driver version number as int */
#define SG_SEIRV_FL_RQS 0x3 /* number of requests in free list */
-#define SG_SEIRV_DEV_FL_RQS 0x4 /* sum(fl rqs) on all of dev's fds */
+#define SG_SEIRV_DEV_FL_RQS 0x4 /* sum(fl rqs) on all dev's fds */
#define SG_SEIRV_TRC_SZ 0x5 /* current size of trace buffer */
#define SG_SEIRV_TRC_MAX_SZ 0x6 /* maximum size of trace buffer */
#define SG_SEIRV_SUBMITTED 0x7 /* number of mrqs submitted+unread */
+#define SG_SEIRV_DEV_SUBMITTED 0x8 /* sum(submiited) on all dev's fds */
/*
* A pointer to the following structure is passed as the third argument to