aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-06-13 05:15:40 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-06-13 05:15:40 +0000
commit3dfb85f55d1cfbff0ae4658395471b9dc3b0a0d4 (patch)
treee49465d10e088245cc70cf03e79f1ac811eaa4b0
parent3e030c2951bee369b5593243bf317bb5a482a35b (diff)
downloadsg3_utils-3dfb85f55d1cfbff0ae4658395471b9dc3b0a0d4.tar.gz
sg_ses: document explicit Element type codes; SG3_UTILS_LINUX_NANO environment variable when Linux sg driver >= 4.0.30; more testing code
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@825 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog8
-rw-r--r--doc/sg3_utils.84
-rw-r--r--doc/sg_decode_sense.818
-rw-r--r--doc/sg_ses.812
-rw-r--r--lib/sg_pt_common.c2
-rw-r--r--lib/sg_pt_linux.c18
-rw-r--r--src/sg_decode_sense.c16
-rw-r--r--testing/sg_tst_async.cpp42
-rw-r--r--testing/sg_tst_ioctl.c71
-rw-r--r--testing/sgh_dd.cpp50
-rw-r--r--testing/sgs_dd.c14
-rw-r--r--testing/uapi_sg.h13
-rw-r--r--utils/hxascdmp.c46
13 files changed, 235 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index 2f869256..8af22c45 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,9 +2,10 @@ 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 [20190517] [svn: r824]
+Changelog for sg3_utils-1.45 [20190612] [svn: r825]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
+ - document explicit Element type codes and example
- sg_opcodes: expand MLU (spc5r20)
- sg_write_buffer: allow comma and period separated
lists when input from stdin
@@ -33,19 +34,20 @@ Changelog for sg3_utils-1.45 [20190517] [svn: r824]
59-fc-wwpn-id.rules
- linux: add nanosecond durations when
SG3_UTILS_LINUX_NANO environment variable given
+ and Linux sg driver >= 4.0.30
- rescan-scsi-bus: widen LUN 0 only scanning
- multiple patches to sync with Suse
- testing/sg_tst_async: fix free_list issue
- testing/sg_tst_ioctl: for sg 4.0 driver
- testing/sg_tst_bidi: for sg 4.0 driver
- - testing/sgs_dd: for share in sg 4.0 driver
- - testing/sgh_dd: rename of sgs_dd to avoid ...
+ - testing/sgh_dd: test request sharing, mreqs...
- testing/sgs_dd: back from archive, for testing
SIGPOLL (SIGIO) and realtime (RT) signals
- sg_pt: add sg_get_opcode_translation() to replace
global pointer to array: sg_opcode_info_arr[]
- extend small SNTL to support read capacity
- utils/hxascdmp: add -o=<offset> option
+ - add -1, -2 and -q options
- sg_io_linux (sg_lib): add sg_linux_sense_print()
- sg_pt_linux: uses sg v4 interface if sg driver
>= 4.0.0 . Force sg v3 always by building with
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index d3f661e0..99bdc0b4 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "May 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG3_UTILS "8" "June 2019" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -100,7 +100,7 @@ sg_persist has SG_PERSIST_IN_RDONLY). See individual utility man pages
for more information.
.PP
There is a Linux specific environment variable called SG3_UTILS_LINUX_NANO
-that if defined and the sg driver in the system is 4.0.0 or later, will
+that if defined and the sg driver in the system is 4.0.30 or later, will
show command durations in nanoseconds rather than the default milliseconds.
Command durations are typically only shown if \-\-verbose is used 3 or more
times. Due to an interface problem (a 32 bit integer that should be 64 bits
diff --git a/doc/sg_decode_sense.8 b/doc/sg_decode_sense.8
index 2396ae31..5a141bf7 100644
--- a/doc/sg_decode_sense.8
+++ b/doc/sg_decode_sense.8
@@ -1,9 +1,9 @@
-.TH SG_DECODE_SENSE "8" "August 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_DECODE_SENSE "8" "June 2019" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_decode_sense \- decode SCSI sense and related data
.SH SYNOPSIS
.B sg_decode_sense
-[\fI\-\-binary=FN\fR] [\fI\-\-cdb\fR] [\fI\-\-err=ES\fR] [\fI\-\-file=FN\fR]
+[\fI\-\-binary=BFN\fR] [\fI\-\-cdb\fR] [\fI\-\-err=ES\fR] [\fI\-\-file=HFN\fR]
[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-nospace\fR] [\fI\-\-status=SS\fR]
[\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-write=WFN\fR]
[H1 H2 H3 ...]
@@ -43,8 +43,8 @@ are ignored apart from \fI\-\-verbose\fR.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
-\fB\-b\fR, \fB\-\-binary\fR=\fIFN\fR
-the sense data is read in binary from a file called \fIFN\fR.
+\fB\-b\fR, \fB\-\-binary\fR=\fIBFN\fR
+the sense data is read in binary from a file called \fIBFN\fR.
.TP
\fB\-c\fR, \fB\-\-cdb\fR
treat the given string of hex arguments as bytes in a SCSI CDB and
@@ -60,12 +60,12 @@ is given two or more times a longer form of the message is output. In all
cases the message is less than 128 characters long with one trailing line
feed. All other command line options and arguments are ignored.
.TP
-\fB\-f\fR, \fB\-\-file\fR=\fIFN\fR
-the sense data is read in ASCII hexadecimal from a file called \fIFN\fR.
+\fB\-f\fR, \fB\-\-file\fR=\fIHFN\fR
+the sense data is read in ASCII hexadecimal from a file called \fIHFN\fR.
The sense data should appear as a sequence of bytes separated by space,
comma, tab or newline. Everything from and including a hash symbol to the
end of that line is ignored. If \fI\-\-nospace\fR is set then no separator
-is required between the ASCII hexadecimal digits in \fIFN\fR with bytes
+is required between the ASCII hexadecimal digits in \fIHFN\fR with bytes
decoded from pairs of ASCII hexadecimal digits.
.TP
\fB\-h\fR, \fB\-\-help\fR
@@ -82,7 +82,7 @@ expect ASCII hexadecimal to be a string of hexadecimal digits with no
spaces between them. Bytes are decoded by taking two hexadecimal digits
at a time, so an even number of digits is expected. The string of
hexadecimal digits may be on the command line (replacing "H1 H2 H3")
-or spread across multiple lines the \fIFN\fR given to \fI\-\-file=\fR.
+or spread across multiple lines the \fIHFN\fR given to \fI\-\-file=\fR.
On the command line, spaces (or other whitespace characters) between
sequences of hexadecimal digits are ignored; the maximum command line
hex string is 1023 characters long.
@@ -148,7 +148,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2010\-2018 Douglas Gilbert
+Copyright \(co 2010\-2019 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index 573c92b0..748d6a4c 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "August 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SES "8" "June 2019" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -430,10 +430,10 @@ Wherever an individual index is applicable, it can be replaced by an
individual index range. It has the form: <first_ii>\-<last_ii>. For
example: '3\-5' will select individual indexes 3, 4 and 5 .
.PP
-To cope with vendor specific Element types (which should be in the range 128
-to 255) the Element type can be given as a number with a leading underscore.
-For example these are equivalent: \fI\-\-index=arr\fR and
-\fI\-\-index=_23\fR since the Array Device Slot Element type value is 23.
+To cope with vendor specific Element types (whose type codes should be in
+the range 128 to 255) the Element type code can be given as a number with
+a leading underscore. For example these are equivalent: \fI\-\-index=arr\fR
+and \fI\-\-index=_23\fR since the Array Device Slot Element type code is 23.
Also \fI\-\-index=ps1\fR and \fI\-\-index=_2_1\fR are equivalent.
.PP
Another example: if the first type header in the Configuration dpage has
@@ -746,7 +746,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2018 Douglas Gilbert
+Copyright \(co 2004\-2019 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/lib/sg_pt_common.c b/lib/sg_pt_common.c
index 242e4774..47e01e1b 100644
--- a/lib/sg_pt_common.c
+++ b/lib/sg_pt_common.c
@@ -31,7 +31,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * scsi_pt_version_str = "3.11 20190128";
+static const char * scsi_pt_version_str = "3.12 20190612";
const char *
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index 4a570f8e..c96c1d1b 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-/* sg_pt_linux version 1.46 20190111 */
+/* sg_pt_linux version 1.47 20190612 */
#include <stdio.h>
@@ -56,7 +56,10 @@
#define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */
/* sg driver displayed format: [x]xyyzz --> [x]x.[y]y.zz */
-#define SG_LINUX_SG_VER_V4 40000 /* lowest version in which v4 available */
+#define SG_LINUX_SG_VER_V4_BASE 40000 /* lowest sg driver version with
+ * v4 interface */
+#define SG_LINUX_SG_VER_V4_FULL 40030 /* lowest version with full v4
+ * interface */
static const char * linux_host_bytes[] = {
"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
@@ -536,7 +539,7 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose)
if (verbose > 4) {
int ver = ptp->sg_version;
- if (ptp->sg_version >= SG_LINUX_SG_VER_V4) {
+ if (ptp->sg_version >= SG_LINUX_SG_VER_V4_BASE) {
#ifdef IGNORE_LINUX_SGV4
pr2ws("%s: sg driver version %d.%02d.%02d but config "
"override back to v3\n", __func__, ver / 10000,
@@ -554,7 +557,7 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose)
} else if (ptp->is_sg)
ptp->sg_version = sg_driver_version_num;
- if (ptp->is_sg && (ptp->sg_version >= SG_LINUX_SG_VER_V4) &&
+ if (ptp->is_sg && (ptp->sg_version >= SG_LINUX_SG_VER_V4_FULL) &&
getenv("SG3_UTILS_LINUX_NANO")) {
struct sg_extended_info sei;
struct sg_extended_info * seip = &sei;
@@ -575,6 +578,11 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose)
pr2ws("%s: dev_fd=%d, succeeding in setting durations "
"to nanoseconds\n", __func__, dev_fd);
}
+ } else if (ptp->is_sg && (ptp->sg_version >= SG_LINUX_SG_VER_V4_BASE)
+ && getenv("SG3_UTILS_LINUX_NANO")) {
+ if (verbose > 2)
+ pr2ws("%s: dev_fd=%d, ignored SG3_UTILS_LINUX_NANO\nbecause "
+ "base version sg version 4 driver\n", __func__, dev_fd);
}
} else {
ptp->is_sg = false;
@@ -1117,7 +1125,7 @@ do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose)
#ifdef IGNORE_LINUX_SGV4
return do_scsi_pt_v3(ptp, fd, time_secs, verbose);
#else
- if (ptp->sg_version >= SG_LINUX_SG_VER_V4)
+ if (ptp->sg_version >= SG_LINUX_SG_VER_V4_BASE)
return do_scsi_pt_v4(ptp, fd, time_secs, verbose);
else
return do_scsi_pt_v3(ptp, fd, time_secs, verbose);
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index e4727593..a71de325 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "1.20 20190516";
+static const char * version_str = "1.21 20190602";
#define MAX_SENSE_LEN 1024 /* max descriptor format actually: 255+8 */
@@ -78,21 +78,21 @@ static char concat_buff[1024];
static void
usage()
{
- pr2serr("Usage: sg_decode_sense [--binary=FN] [--cdb] [--err=ES] "
- "[--file=FN]\n"
+ pr2serr("Usage: sg_decode_sense [--binary=BFN] [--cdb] [--err=ES] "
+ "[--file=HFN]\n"
" [--help] [--hex] [--nospace] [--status=SS] "
"[--verbose]\n"
" [--version] [--write=WFN] H1 H2 H3 ...\n"
" where:\n"
- " --binary=FN|-b FN FN is a file name to read sense "
+ " --binary=BFN|-b BFN BFN is a file name to read sense "
"data in\n"
- " binary from. If FN is '-' then read "
+ " binary from. If BFN is '-' then read "
"from stdin\n"
" --cdb|-c decode given hex as cdb rather than "
"sense data\n"
" --err=ES|-e ES ES is Exit Status from utility in this "
"package\n"
- " --file=FN|-f FN FN is a file name from which to read "
+ " --file=HFN|-f HFN HFN is a file name from which to read "
"sense data\n"
" in ASCII hexadecimal. Interpret '-' "
"as stdin\n"
@@ -136,7 +136,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
switch (c) {
case 'b':
if (op->fname) {
- pr2serr("expect only one '--binary=FN' or '--file=FN' "
+ pr2serr("expect only one '--binary=BFN' or '--file=BFN' "
"option\n");
return SG_LIB_CONTRADICT;
}
@@ -157,7 +157,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
break;
case 'f':
if (op->fname) {
- pr2serr("expect only one '--binary=FN' or '--file=FN' "
+ pr2serr("expect only one '--binary=HFN' or '--file=HFN' "
"option\n");
return SG_LIB_CONTRADICT;
}
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp
index d6b1c5d0..150abea9 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.34 20190506";
+static const char * version_str = "1.35 20190612";
static const char * util_name = "sg_tst_async";
/* This is a test program for checking the async usage of the Linux sg
@@ -196,7 +196,8 @@ struct opts_t {
bool mmap_io;
bool no_xfer;
bool pack_id_force;
- bool sg_vn_ge_30901;
+ bool sg_vn_ge_40000;
+ bool sg_vn_ge_40030;
bool submit;
bool verbose_given;
bool v3;
@@ -1030,12 +1031,12 @@ work_thread(int id, struct opts_t * op)
pr2serr_lk("ioctl(SG_SET_FORCE_PACK_ID) failed, errno=%d %s\n",
errno, strerror(errno));
}
- if (op->sg_vn_ge_30901) {
+ if (op->sg_vn_ge_40000) {
if (ioctl(sg_fd, SG_GET_RESERVED_SIZE, &k) >= 0) {
if (needed_sz > k)
ioctl(sg_fd, SG_SET_RESERVED_SIZE, &needed_sz);
}
- if (op->cmd_time || op->masync) {
+ if (op->sg_vn_ge_40030 && (op->cmd_time || op->masync)) {
struct sg_extended_info sei;
struct sg_extended_info * seip;
@@ -1152,7 +1153,7 @@ work_thread(int id, struct opts_t * op)
}
if (vb && ! once1000 && num_outstanding >= 1000) {
int num_waiting;
- int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+ int num_subm = (op->sg_vn_ge_40030) ? num_submitted(sg_fd) : -1;
once1000 = true;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
@@ -1166,7 +1167,7 @@ work_thread(int id, struct opts_t * op)
}
if (vb && ! once5000 && num_outstanding >= 5000) {
int num_waiting;
- int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+ int num_subm = (op->sg_vn_ge_40030) ? num_submitted(sg_fd) : -1;
once5000 = true;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
@@ -1179,7 +1180,7 @@ work_thread(int id, struct opts_t * op)
}
if (vb && ! once_7000 && num_outstanding >= 7000) {
int num_waiting;
- int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+ int num_subm = (op->sg_vn_ge_40030) ? num_submitted(sg_fd) : -1;
once_7000 = true;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
@@ -1192,7 +1193,7 @@ work_thread(int id, struct opts_t * op)
}
if (vb && ! once10_000 && num_outstanding >= 10000) {
int num_waiting;
- int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+ int num_subm = (op->sg_vn_ge_40030) ? num_submitted(sg_fd) : -1;
once10_000 = true;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
@@ -1205,7 +1206,7 @@ work_thread(int id, struct opts_t * op)
}
if (vb && ! once20_000 && num_outstanding >= 20000) {
int num_waiting;
- int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+ int num_subm = (op->sg_vn_ge_40030) ? num_submitted(sg_fd) : -1;
once20_000 = true;
if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
@@ -1361,7 +1362,7 @@ work_thread(int id, struct opts_t * op)
case MYQD_HIGH:
default:
if (op->ovn > 0) {
- if (op->sg_vn_ge_30901) {
+ if (op->sg_vn_ge_40030) {
int num_subm = num_submitted(sg_fd);
if (num_subm > op->ovn) {
@@ -1381,7 +1382,7 @@ work_thread(int id, struct opts_t * op)
}
}
} else { /* nothing waiting to be read */
- if (op->sg_vn_ge_30901) {
+ if (op->sg_vn_ge_40030) {
int val = num_submitted(sg_fd);
if (0 == val) {
@@ -1421,7 +1422,7 @@ work_thread(int id, struct opts_t * op)
if (MYQD_HIGH == op->myqd) {
num_to_read = 0;
if (op->ovn) {
- if (op->sg_vn_ge_30901) {
+ if (op->sg_vn_ge_40030) {
int num_subm = num_submitted(sg_fd);
if (num_subm > op->ovn)
@@ -1489,7 +1490,7 @@ work_thread(int id, struct opts_t * op)
}
break;
}
- if (op->cmd_time && op->sg_vn_ge_30901)
+ if (op->cmd_time && op->sg_vn_ge_40030)
sum_nanosecs += nanosecs;
++thr_async_finishes;
--num_outstanding;
@@ -1572,7 +1573,7 @@ work_thread(int id, struct opts_t * op)
fin_eagain_count += thr_fin_eagain_count;
fin_ebusy_count += thr_fin_ebusy_count;
start_edom_count += thr_start_edom_count;
- if (op->cmd_time && op->sg_vn_ge_30901 && (npt > 0)) {
+ if (op->cmd_time && op->sg_vn_ge_40030 && (npt > 0)) {
pr2serr_lk("t_id=%d average nanosecs per cmd: %" PRId64
"\n", id, sum_nanosecs / npt);
}
@@ -2070,8 +2071,17 @@ 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) {
- op->sg_vn_ge_30901 = true;
+ } else if (sg_ver_num >= 40030) {
+ op->sg_vn_ge_40030 = true;
+ op->sg_vn_ge_40000 = true;
+ if (! (op->v3_given || op->v4_given)) {
+ op->v4 = true;
+ op->v3 = false;
+ op->submit = true;
+ }
+ } else if (sg_ver_num >= 40000) {
+ op->sg_vn_ge_40030 = false;
+ op->sg_vn_ge_40000 = true;
if (! (op->v3_given || op->v4_given)) {
op->v4 = true;
op->v3 = false;
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index 8629a684..b62e5233 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#include <string.h>
#include <errno.h>
+#include <time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -57,7 +58,7 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.10 20190506";
+static const char * version_str = "Version: 1.11 20190523";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
@@ -97,6 +98,7 @@ static int q_len = DEF_Q_LEN;
static int sleep_secs = 0;
static int reserve_buff_sz = DEF_RESERVE_BUFF_SZ;
static int num_mrqs = 0;
+static int num_sgnw = 0;
static int verbose = 0;
static const char * relative_cp = NULL;
@@ -107,7 +109,8 @@ usage(void)
{
printf("Usage: sg_tst_ioctl [-3] [-f] [-h] [-l=Q_LEN] [-m=MRQS[,I|S]] "
"[-M] [-o]\n"
- " [-r=SZ] [-s=SEC] [-S] [-t] [-v] [-V] [-w]\n"
+ " [-r=SZ] [-s=SEC] [-S] [-t] [-T=NUM] [-v] "
+ "[-V] [-w]\n"
" <sg_device> [<sg_device2>]\n"
" where:\n"
" -f fork and test share between processes\n"
@@ -129,6 +132,8 @@ usage(void)
" -S size of interface structures plus ioctl "
"values\n"
" -t queue_at_tail (def: q_at_head)\n"
+ " -T=NUM time overhead of NUM invocations of\n"
+ " 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");
@@ -238,7 +243,7 @@ sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
static void
set_more_async(int fd)
{
- if (sg_drv_ver_num > 40000) {
+ if (sg_drv_ver_num > 40030) {
struct sg_extended_info sei;
struct sg_extended_info * seip;
@@ -628,6 +633,7 @@ int
main(int argc, char * argv[])
{
bool done;
+ bool nw_given = false;
int sg_fd, k, ok, pack_id, num_waiting;
int res = 0;
int sg_fd2 = -1;
@@ -711,7 +717,15 @@ main(int argc, char * argv[])
show_size_value = true;
else if (0 == memcmp("-t", argv[k], 2))
q_at_tail = true;
- else if (0 == memcmp("-vvvvvvv", argv[k], 8))
+ else if (0 == memcmp("-T=", argv[k], 3)) {
+ num_sgnw = sg_get_num(argv[k] + 3);
+ if (num_sgnw < 0) {
+ printf("Expect -T= to take a number >= 0\n");
+ file_name = 0;
+ break;
+ }
+ nw_given = true;
+ } else if (0 == memcmp("-vvvvvvv", argv[k], 8))
verbose += 7;
else if (0 == memcmp("-vvvvvv", argv[k], 7))
verbose += 6;
@@ -814,6 +828,55 @@ main(int argc, char * argv[])
goto out;
}
printf("Linux sg driver version: %d\n", sg_drv_ver_num);
+
+ if (nw_given) { /* time ioctl(SG_GET_NUM_WAITING) */
+ int nw, sum_nw;
+ struct timespec start_tm, fin_tm, res_tm;
+
+ printf("Timing %d calls to ioctl(SG_GET_NUM_WAITING)\n", num_sgnw);
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
+ res = errno;
+ perror("start clock_gettime() failed:");
+ goto out;
+ }
+ for (k = 0, sum_nw = 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 "
+ "errno=%d\n", k, res);
+ goto out;
+ }
+ }
+ if (0 != clock_gettime(CLOCK_MONOTONIC, &fin_tm)) {
+ res = errno;
+ perror("finish clock_gettime() failed:");
+ goto out;
+ }
+ res_tm.tv_sec = fin_tm.tv_sec - start_tm.tv_sec;
+ res_tm.tv_nsec = fin_tm.tv_nsec - start_tm.tv_nsec;
+ if (res_tm.tv_nsec < 0) {
+ --res_tm.tv_sec;
+ res_tm.tv_nsec += 1000000000;
+ }
+ if (verbose) {
+ if (verbose > 1)
+ printf("sum of num_waiting_s=%d\n", sum_nw);
+ printf("elapsed time (nanosecond precision): %d.%09d secs\n",
+ (int)res_tm.tv_sec, (int)res_tm.tv_nsec);
+ } else
+ printf("elapsed time: %d.%06d secs\n", (int)res_tm.tv_sec,
+ (int)(res_tm.tv_nsec / 1000));
+ if (num_sgnw >= 100) {
+ double m = (double)res_tm.tv_sec +
+ ((double)res_tm.tv_nsec / 1000000000.0);
+
+ if (m > 0.000001)
+ printf("Calls per second: %.2f\n", (double)num_sgnw / m);
+ }
+
+ res = 0;
+ goto out;
+ }
if (more_async && !do_v3_only)
set_more_async(sg_fd);
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 185044f1..2de7bbaa 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.31 20190515";
+static const char * version_str = "1.33 20190612";
#ifdef __GNUC__
#ifndef __clang__
@@ -213,6 +213,7 @@ typedef struct global_collection
int sum_of_resids; /* -/ */
int debug; /* both -v and deb=VERB bump this field */
int dry_run;
+ bool aen_given;
bool ofile_given;
bool ofile2_given;
bool unit_nanosec; /* default duration unit is millisecond */
@@ -277,6 +278,8 @@ static atomic<long int> pos_index(0);
static atomic<int> num_ebusy(0);
static atomic<int> num_start_eagain(0);
static atomic<int> num_fin_eagain(0);
+static atomic<int> num_abort_req(0);
+static atomic<int> num_abort_req_success(0);
static sigset_t signal_set;
static pthread_t sig_listen_thread_id;
@@ -1839,6 +1842,10 @@ do_v4:
}
if ((rep->aen > 0) && (rep->rep_count > 0)) {
if (0 == (rep->rq_id % rep->aen)) {
+ struct timespec tspec = {0, 4000 /* 4 usecs */};
+
+ nanosleep(&tspec, NULL);
+#if 0
struct pollfd a_poll;
a_poll.fd = fd;
@@ -1849,15 +1856,25 @@ do_v4:
pr2serr_lk("%s: poll() failed: %s [%d]\n",
__func__, safe_strerror(errno), errno);
else if (0 == res) { /* timeout, cmd still inflight, so abort */
- res = ioctl(fd, SG_IOABORT, h4p);
- if (res < 0)
+ }
+#endif
+ ++num_abort_req;
+ res = ioctl(fd, SG_IOABORT, h4p);
+ if (res < 0) {
+ err = errno;
+ if (ENODATA == err)
+ pr2serr_lk("%s: ioctl(SG_IOABORT) no match on "
+ "pack_id=%d\n", __func__, pack_id);
+ else
pr2serr_lk("%s: ioctl(SG_IOABORT) failed: %s [%d]\n",
- __func__, safe_strerror(errno), errno);
- else if (rep->debug > 1)
- pr2serr_lk("%s: sending ioctl(SG_IOABORT) on rq_id=%d\n",
- __func__, pack_id);
- } /* else got response, too late for timeout, so skip */
- }
+ __func__, safe_strerror(err), err);
+ } else {
+ ++num_abort_req_success;
+ if (rep->debug > 1)
+ pr2serr_lk("%s: sent ioctl(SG_IOABORT) on rq_id=%d, "
+ "success\n", __func__, pack_id);
+ }
+ } /* else got response, too late for timeout, so skip */
}
return 0;
}
@@ -2499,6 +2516,7 @@ main(int argc, char * argv[])
my_name);
return SG_LIB_SYNTAX_ERROR;
}
+ clp->aen_given = true;
} else if (0 == strcmp(key, "bpt")) {
clp->bpt = sg_get_num(buf);
if (-1 == clp->bpt) {
@@ -2734,6 +2752,13 @@ main(int argc, char * argv[])
pr2serr("dio flag can only be used with noshare flag\n");
return SG_LIB_SYNTAX_ERROR;
}
+ if ((clp->in_flags.noshare || clp->out_flags.noshare) &&
+ (clp->nmrqs > 0)) {
+ clp->nmrqs = 0;
+ clp->mrq_cmds = false;
+ if (clp->debug)
+ pr2serr("Ignoring multi-request because noshare flag given\n");
+ }
/* defaulting transfer size to 128*2048 for CD/DVDs is too large
for the block layer in lk 2.6 and results in an EIO on the
SG_IO ioctl. So reduce it in that case. */
@@ -3248,9 +3273,12 @@ fini:
pr2serr("Number of start EAGAINs: %d\n", num_start_eagain.load());
if (clp->debug && (num_fin_eagain > 0))
pr2serr("Number of finish EAGAINs: %d\n", num_fin_eagain.load());
- if (clp->debug && (num_ebusy > 0)) {
+ if (clp->debug && (num_ebusy > 0))
pr2serr("Number of EBUSYs: %d\n", num_ebusy.load());
-
+ if (clp->debug && clp->aen_given && (num_abort_req > 0)) {
+ pr2serr("Number of Aborts: %d\n", num_abort_req.load());
+ pr2serr("Number of successful Aborts: %d\n",
+ num_abort_req_success.load());
}
return (res >= 0) ? res : SG_LIB_CAT_OTHER;
}
diff --git a/testing/sgs_dd.c b/testing/sgs_dd.c
index e0ff7b4b..53c8b01f 100644
--- a/testing/sgs_dd.c
+++ b/testing/sgs_dd.c
@@ -78,7 +78,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "4.08 20190515";
+static const char * version_str = "4.09 20190612";
static const char * my_name = "sgs_dd";
#define DEF_BLOCK_SIZE 512
@@ -171,6 +171,7 @@ typedef struct request_collection
} Rq_coll;
static bool sgs_old_sg_driver = false; /* true if VERSION_NUM < 4.00.00 */
+static bool sgs_full_v4_sg_driver = false; /* set if VERSION_NUM >= 4.00.30 */
static bool sgs_nanosec_unit = false;
@@ -482,19 +483,22 @@ sz_reserve(int fd, int bs, int bpt, bool rt_sig, bool vb)
if ((res < 0) || (t < 30000)) {
fprintf(stderr, "sgs_dd: sg driver prior to 3.0.00\n");
return 1;
- }
- else if (t < 40000) {
+ } else if (t < 40000) {
if (vb)
fprintf(stderr, "sgs_dd: warning: sg driver prior to 4.0.00\n");
sgs_old_sg_driver = true;
- }
+ } else if (t < 40030) {
+ sgs_old_sg_driver = false;
+ sgs_full_v4_sg_driver = false;
+ } else
+ sgs_full_v4_sg_driver = true;
res = 0;
t = bs * bpt;
res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
if (res < 0)
perror("sgs_dd: SG_SET_RESERVED_SIZE error");
- if (sgs_nanosec_unit) {
+ if (sgs_nanosec_unit && sgs_full_v4_sg_driver) {
memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS;
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index fa7f2ea3..348918f9 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.11 (20190502)
+ * Version 4.0.12 (20190521)
* This version is for Linux 4 and 5 series kernels.
*
* Documentation
@@ -31,7 +31,11 @@
#include <linux/types.h>
#include <linux/major.h>
-/* bsg.h contains the sg v4 user space interface structure (sg_io_v4). */
+/*
+ * bsg.h contains the sg v4 user space interface structure (sg_io_v4).
+ * That structure is also used as the controlling object when multiple
+ * requests are issued with one ioctl() call.
+ */
#include <linux/bsg.h>
/*
@@ -111,8 +115,8 @@ typedef struct sg_io_hdr {
#define SGV4_FLAG_Q_AT_HEAD SG_FLAG_Q_AT_HEAD
#define SGV4_FLAG_COMPLETE_B4 0x100
#define SGV4_FLAG_SIG_ON_OTHER 0x200
-#define SGV4_FLAG_IMMED 0x400 /* for polling with SG_IOR, ignored in SG_IOS */
-#define SGV4_FLAG_STOP_IF 0x800 /* Stops sync mrq if error or warning */
+#define SGV4_FLAG_IMMED 0x400 /* for polling with SG_IOR, ignored in SG_IOS */
+#define SGV4_FLAG_STOP_IF 0x800 /* Stops sync mrq if error or warning */
#define SGV4_FLAG_DEV_SCOPE 0x1000 /* permit SG_IOABORT to have wider scope */
#define SGV4_FLAG_SHARE 0x2000 /* share IO buffer; needs SG_SEIM_SHARE_FD */
#define SGV4_FLAG_DO_ON_OTHER 0x4000 /* available on either of shared pair */
@@ -460,7 +464,6 @@ struct sg_header {
/* 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
diff --git a/utils/hxascdmp.c b/utils/hxascdmp.c
index 4184c037..f08d0313 100644
--- a/utils/hxascdmp.c
+++ b/utils/hxascdmp.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -23,7 +24,7 @@
static int bytes_per_line = DEF_BYTES_PER_LINE;
-static const char * version_str = "1.17 20190210";
+static const char * version_str = "1.11 20190527";
#define CHARS_PER_HEX_BYTE 3
#define BINARY_START_COL 6
@@ -317,9 +318,13 @@ dStrHexOnly(const char* str, int len, long start, int noAddr)
static void
usage()
{
- fprintf(stderr, "Usage: hxascdmp [-b=<n>] [-h] [-H] [-N] [-V] [-?] "
- "[<file>+]\n");
+ fprintf(stderr, "Usage: hxascdmp [-1] [-2] [-b=<n>] [-h] [-H] [-N] "
+ "[-o=<off>] [-q]\n"
+ " [-V] [-?] [<file>+]\n");
fprintf(stderr, " where:\n");
+ fprintf(stderr, " -1 print first byte in hex, prepend '0x' "
+ "if '-H' given\n");
+ fprintf(stderr, " -2 like '-1' but print first two bytes\n");
fprintf(stderr, " -b=<n> bytes per line to display "
"(def: 16)\n");
fprintf(stderr, " -h print this usage message\n");
@@ -328,6 +333,8 @@ usage()
fprintf(stderr, " -N no address, start in first column\n");
fprintf(stderr, " -o=<off> start decoding at byte <off>. Suffix "
"multipliers allowed\n");
+ fprintf(stderr, " -q quiet: suppress output of header "
+ "info\n");
fprintf(stderr, " -V print version string then exits\n");
fprintf(stderr, " -? print this usage message\n");
fprintf(stderr, " <file>+ reads file(s) and outputs each "
@@ -350,6 +357,9 @@ main(int argc, const char ** argv)
int noAddr = 0;
int doVersion = 0;
int hasFilename = 0;
+ int quiet = 0;
+ int print1 = 0;
+ int print2 = 0;
int ret = 0;
const char * cp;
@@ -375,6 +385,12 @@ main(int argc, const char ** argv)
offset = off;
} else if ((len > 1) && ('-' == cp[0]) && ('-' != cp[1])) {
res = 0;
+ n = num_chs_in_str(cp + 1, len - 1, '1');
+ print1 += n;
+ res += n;
+ n = num_chs_in_str(cp + 1, len - 1, '2');
+ print2 += n;
+ res += n;
n = num_chs_in_str(cp + 1, len - 1, 'h');
doHelp += n;
res += n;
@@ -384,6 +400,9 @@ main(int argc, const char ** argv)
n = num_chs_in_str(cp + 1, len - 1, 'N');
noAddr += n;
res += n;
+ n = num_chs_in_str(cp + 1, len - 1, 'q');
+ quiet += n;
+ res += n;
n = num_chs_in_str(cp + 1, len - 1, 'V');
doVersion += n;
res += n;
@@ -405,6 +424,8 @@ main(int argc, const char ** argv)
hasFilename = 1;
break;
}
+ if (print2)
+ print1 += print2 + print2;
}
if (doVersion) {
printf("%s\n", version_str);
@@ -443,9 +464,26 @@ main(int argc, const char ** argv)
start = offset;
} else
start = 0;
- if (! doHex)
+ if (! (doHex || quiet || print1))
printf("ASCII hex dump of file: %s\n", argv[k]);
while ((res = read(inFile, buff, num)) > 0) {
+ if (print1) {
+ if (1 == print1) {
+ if (doHex)
+ printf("0x%02x\n", (uint8_t)(buff[0]));
+ else
+ printf("%02x\n", (uint8_t)(buff[0]));
+ } else {
+ uint16_t us;
+
+ memcpy(&us, buff, 2);
+ if (doHex)
+ printf("0x%04x\n", us);
+ else
+ printf("%04x\n", us);
+ }
+ break;
+ }
if (doHex)
dStrHexOnly(buff, res, start, noAddr);
else