aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-01-11 16:25:37 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-01-11 16:25:37 +0000
commit68c8a6cc83711259bd90e6296c63ee384d477b18 (patch)
treeb56c5cbf87c23c62aac6bbb32714a488a81896b5
parent660ac667940dc7bb188b4e2d0ec9c7f2dd444fc0 (diff)
downloadsg3_utils-68c8a6cc83711259bd90e6296c63ee384d477b18.tar.gz
sg_logs: add Command duration limits statistics lpage; sg_opcodes: include RWCDLP field as extension of CDLP field; sgh_dd work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@838 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog10
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg3_utils.84
-rw-r--r--doc/sg_logs.84
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_logs.c96
-rw-r--r--src/sg_modes.c8
-rw-r--r--src/sg_opcodes.c13
-rw-r--r--testing/sgh_dd.cpp46
9 files changed, 150 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 4762214b..99151f83 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 [20191227] [svn: r837]
+Changelog for sg3_utils-1.45 [20200111] [svn: r838]
- sg_get_elem_status: new utility [sbc4r16]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
@@ -10,7 +10,9 @@ Changelog for sg3_utils-1.45 [20191227] [svn: r837]
- rename 'SAS SlimLine' to SlimSAS [ses4r02]
- add --inhex=FN, equivalent to --data=@FN, for
compatibility with other utilities
- - sg_opcodes: expand MLU (spc5r20)
+ - sg_opcodes: expand MLU (now 2 bits, spc5r20)
+ - include RWCDLP field as extension of CDLP
+ field (spc5r01)
- sg_write_buffer: allow comma and period separated
lists when input from stdin
- sg_inq: update version descriptors to spc5r21
@@ -30,8 +32,8 @@ Changelog for sg3_utils-1.45 [20191227] [svn: r837]
- sg_scan (win32): expand limits for big arrays
- sg_modes: placeholders for Command duration limit
T2A and T2B mpages (sbc4r17)
- - sg_logs: placeholder for Command duration limits
- statistics lpage (sbc4r17)
+ - sg_logs: add Command duration limits statistics
+ lpage (spc6r01)
- zoned block device statistics log page: shorten
counter fields from 8 to 4 bytes (zbc2r02)
- new field in this log page (zbc2r04)
diff --git a/debian/changelog b/debian/changelog
index a3f3060e..ab35da37 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.45-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Fri, 06 Dec 2019 14:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Wed, 01 Jan 2020 14:00:00 -0500
sg3-utils (1.44-0.1) unstable; urgency=low
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index a85bcf25..ef1e5f47 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "December 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG3_UTILS "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -752,7 +752,7 @@ CREDITS file and individual source files (in the 'src' directory).
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 1999\-2019 Douglas Gilbert
+Copyright \(co 1999\-2020 Douglas Gilbert
.br
Some utilities are distributed under a GPL version 2 license while
others, usually more recent ones, are under a FreeBSD license. The files
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index 0158363e..216f8d7e 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -1,4 +1,4 @@
-.TH SG_LOGS "8" "October 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_LOGS "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_logs \- access log pages with SCSI LOG SENSE command
.SH SYNOPSIS
@@ -482,7 +482,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2002\-2019 Douglas Gilbert
+Copyright \(co 2002\-2020 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/sg3_utils.spec b/sg3_utils.spec
index a15b0c17..5dbc2c89 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Fri Dec 06 2019 - dgilbert at interlog dot com
+* Wed Jan 01 2020 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.45
diff --git a/src/sg_logs.c b/src/sg_logs.c
index c65ecb91..434217ad 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2000-2019 D. Gilbert
+ * Copyright (C) 2000-2020 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)
@@ -36,7 +36,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.80 20191205"; /* spc5r22 + sbc4r17 */
+static const char * version_str = "1.81 20200110"; /* spc6r01 + sbc4r17 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -70,7 +70,7 @@ static const char * version_str = "1.80 20191205"; /* spc5r22 + sbc4r17 */
#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 CMD_DUR_LIMITS_SUBPG 0x21 /* page 0x19 */
#define ENV_REPORTING_SUBPG 0x1 /* page 0xd */
#define UTILIZATION_SUBPG 0x1 /* page 0xe */
#define ENV_LIMITS_SUBPG 0x2 /* page 0xd */
@@ -294,6 +294,8 @@ static bool show_environmental_reporting_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_environmental_limits_page(const uint8_t * resp, int len,
const struct opts_t * op);
+static bool show_cmd_dur_limits_page(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_data_compression_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_tape_alert_ssc_page(const uint8_t * resp, int len,
@@ -408,7 +410,8 @@ static struct log_elem log_arr[] = {
{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? */ },
+ "Commmand duration limits statistics", "cdl",
+ show_cmd_dur_limits_page /* spc6r01 */ },
{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",
@@ -1984,7 +1987,7 @@ show_environmental_reporting_page(const uint8_t * resp, int len,
temperature_str(bp[11], true, b, blen));
}
} else
- printf(" <<unexpect parameter code 0x%x\n", pc);
+ printf(" <<unexpected parameter code 0x%x\n", pc);
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -2066,7 +2069,7 @@ show_environmental_limits_page(const uint8_t * resp, int len,
printf(" Low operating relative humidity limit trigger: %s\n",
humidity_str(bp[11], false, b, blen));
} else
- printf(" <<unexpect parameter code 0x%x\n", pc);
+ printf(" <<unexpected parameter code 0x%x\n", pc);
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -2079,6 +2082,87 @@ skip:
return true;
}
+/* CMD_DUR_LIMITS_SUBPG [0x19,0x21] introduced: SPC-6 (rev 01) */
+static bool
+show_cmd_dur_limits_page(const uint8_t * resp, int len,
+ const struct opts_t * op)
+{
+ int num, pl, pc;
+ const uint8_t * bp;
+ char str[PCB_STR_LEN];
+
+ if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
+ printf("Command duration limits page [0x19,0x21]\n");
+ num = len - 4;
+ bp = &resp[0] + 4;
+ while (num > 3) {
+ pc = sg_get_unaligned_be16(bp + 0);
+ pl = bp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw(bp, pl);
+ break;
+ } else if (op->do_hex) {
+ hex2stdout(bp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x1:
+ printf(" Number of READ commands = %" PRIu64 "\n",
+ sg_get_unaligned_be64(bp + 4));
+ break;
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ printf(" Command duration limit T2%s %d [Parameter code 0x%x]:\n",
+ ((pc > 0x20) ? "B" : "A"),
+ ((pc > 0x20) ? (pc - 0x20) : (pc - 0x10)), pc);
+ printf(" Number of inactive target miss commands = %u\n",
+ sg_get_unaligned_be32(bp + 4));
+ printf(" Number of active target miss commands = %u\n",
+ sg_get_unaligned_be32(bp + 8));
+ printf(" Number of latency miss commands = %u\n",
+ sg_get_unaligned_be32(bp + 12));
+ printf(" Number of nonconforming miss commands = %u\n",
+ sg_get_unaligned_be32(bp + 16));
+ printf(" Number of predictive latency miss commands = %u\n",
+ sg_get_unaligned_be32(bp + 20));
+ printf(" Number of latency misses attributable to errors = %u\n",
+ sg_get_unaligned_be32(bp + 24));
+ printf(" Number of latency misses attributable to deferred "
+ "errors = %u\n", sg_get_unaligned_be32(bp + 28));
+ printf(" Number of latency misses attributable to background "
+ "operations = %u\n", sg_get_unaligned_be32(bp + 32));
+ break;
+ default:
+ printf(" <<unexpected parameter code 0x%x\n", pc);
+ break;
+ }
+ if (op->do_pcb)
+ printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
+ if (op->filter_given)
+ break;
+skip:
+ num -= pl;
+ bp += pl;
+ }
+ return true;
+}
+
/* Tape usage: Vendor specific (LTO-5 and LTO-6): 0x30 */
static bool
show_tape_usage_page(const uint8_t * resp, int len, const struct opts_t * op)
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 17617cfb..dc8c4691 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2019 D. Gilbert
+ * Copyright (C) 2000-2020 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.68 20190405";
+static const char * version_str = "1.69 20200111";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -118,8 +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? */
+ {0xa, 0x7, "cdt2a", "Command duration limit T2A"}, /* spc6r01 */
+ {0xa, 0x8, "cdt2b", "Command duration limit T2B"}, /* spc6r01 */
{0x15, 0x0, "ext_", "Extended"},
{0x16, 0x0, "edts", "Extended device-type specific"},
{0x18, 0x0, "pslu", "Protocol specific lu"},
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 7c892c0f..6f160ff8 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2004-2019 D. Gilbert
+ * Copyright (C) 2004-2020 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)
@@ -33,7 +33,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.67 20191220"; /* spc5r20 */
+static const char * version_str = "0.68 20200111"; /* spc6r01 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -775,17 +775,20 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op,
"%s\n", opcode, sa_buff,
sg_get_unaligned_be16(bp + 6), name_buff);
} else { /* RCTD clear in cdb */
+ /* treat RWCDLP (1 bit) and CDLP (2 bits) as a 3 bit field */
+ int cdl_mp = ((byt5 >> 2) & 0x3) + ((0x40 & byt5) ? 4 : 0);
+
if (op->do_compact)
printf(" %.2x%c%.4s %s\n", bp[0], (sa_v ? ',' : ' '),
sa_buff, name_buff);
else if (op->do_mlu)
printf(" %.2x %.4s %3d %2d,%d %s\n", bp[0],
sa_buff, sg_get_unaligned_be16(bp + 6),
- (byt5 >> 2) & 0x3, !!(0x10 & byt5), name_buff);
+ cdl_mp, ((byt5 >> 4) & 0x3), name_buff);
else
printf(" %.2x %.4s %3d %2d %s\n", bp[0],
- sa_buff, sg_get_unaligned_be16(bp + 6),
- ((byt5 >> 4) & 0x3) /* MLU */, name_buff);
+ sa_buff, sg_get_unaligned_be16(bp + 6), cdl_mp,
+ name_buff);
}
if (op->do_mask) {
int cdb_sz;
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 73a2e677..385826c6 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -2,7 +2,7 @@
* A utility program for copying files. Specialised for "files" that
* represent devices that understand the SCSI command set.
*
- * Copyright (C) 2018-2019 D. Gilbert
+ * Copyright (C) 2018-2020 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)
@@ -108,7 +108,7 @@
using namespace std;
-static const char * version_str = "1.61 20191226";
+static const char * version_str = "1.64 20200110";
#ifdef __GNUC__
#ifndef __clang__
@@ -121,7 +121,7 @@ static const char * version_str = "1.61 20191226";
/* comment out following line to stop ioctl(SG_CTL_FLAGM_SNAP_DEV) */
-// #define SGH_DD_SNAP_DEV 1
+#define SGH_DD_SNAP_DEV 1
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -161,6 +161,7 @@ static const char * version_str = "1.61 20191226";
#define EBUFF_SZ 768
#define PROC_SCSI_SG_VERSION "/proc/scsi/sg/version"
+#define SYS_SCSI_SG_VERSION "/sys/module/sg/version"
struct flags_t {
bool append;
@@ -630,6 +631,18 @@ fetch_sg_version(void)
if (fp && fgets(b, sizeof(b) - 1, fp)) {
if (1 == sscanf(b, "%d", &sg_version))
have_sg_version = !!sg_version;
+ } else {
+ int j, k, l;
+
+ if (fp)
+ fclose(fp);
+ fp = fopen(SYS_SCSI_SG_VERSION, "r");
+ if (fp && fgets(b, sizeof(b) - 1, fp)) {
+ if (3 == sscanf(b, "%d.%d.%d", &j, &k, &l)) {
+ sg_version = (j * 10000) + (k * 100) + l;
+ have_sg_version = !!sg_version;
+ }
+ }
}
if (fp)
fclose(fp);
@@ -1424,7 +1437,7 @@ read_write_thread(void * v_tip)
pthread_cleanup_push(cleanup_in, (void *)clp);
if (in_is_sg) {
- if (rep->swait)
+ if (rep->swait && rep->has_share)
sg_in_out_interleave(clp, rep, deferred_arr);
else /* unlocks in_mutex mid op */
sg_in_rd_cmd(clp, rep, deferred_arr);
@@ -1485,7 +1498,8 @@ skip_force_out_sequence:
/* Output to OFILE */
wr_blks = rep->num_blks;
if (out_is_sg) {
- if (rep->swait) { /* done already in sg_in_out_interleave() */
+ if (rep->swait && rep->has_share) {
+ /* done already in sg_in_out_interleave() */
status = pthread_mutex_unlock(&clp->out_mutex);
if (0 != status) err_exit(status, "unlock out_mutex");
} else /* release out_mtx */
@@ -2387,8 +2401,11 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
ctl_v4.request = (uint64_t)cmd_ap;
}
ctl_v4.flags = SGV4_FLAG_MULTIPLE_REQS;
- if (! clp->mrq_async)
+ if (! clp->mrq_async) {
ctl_v4.flags |= SGV4_FLAG_STOP_IF;
+ if (clp->in_flags.mrq_svb || clp->in_flags.mrq_svb)
+ ctl_v4.flags |= SGV4_FLAG_SHARE;
+ }
ctl_v4.dout_xferp = (uint64_t)a_v4p; /* request array */
ctl_v4.dout_xfer_len = nrq * sizeof(*a_v4p);
ctl_v4.din_xferp = (uint64_t)a_v4p; /* response array */
@@ -2493,6 +2510,7 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
goto fini;
}
+try_again:
if (clp->unbalanced_mrq) {
if (!after1 && (clp->debug > 1)) {
after1 = true;
@@ -2508,13 +2526,11 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
}
res = ioctl(fd, SG_IOSUBMIT, &ctl_v4);
} else if (clp->in_flags.mrq_svb || clp->in_flags.mrq_svb) {
- ctl_v4.flags |= SGV4_FLAG_SHARE;
iosub_str = "SUBMIT(shared_variable_blocking)";
if (!after1 && (clp->debug > 1)) {
after1 = true;
pr2serr_lk("%s: %s\n", __func__, mrq_svb_s);
}
-// v4hdr_out_lk("cop: shared_variable_blocking", &ctl_v4, id);
res = ioctl(fd, SG_IOSUBMIT, &ctl_v4);
} else {
iosub_str = "SG_IO(ordered_blocking)";
@@ -2526,9 +2542,16 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
}
}
if (res < 0) {
+ int err = errno;
+
+ if (EBUSY == err) {
+ ++num_ebusy;
+ std::this_thread::yield();/* allow another thread to progress */
+ goto try_again;
+ }
pr2serr_lk("%s: ioctl(SG_IO%s, %s)-->%d, errno=%d: %s\n",
__func__, iosub_str, sg_flags_str(ctl_v4.flags, b_len, b),
- res, errno, strerror(errno));
+ res, err, strerror(err));
res = -1;
goto fini;
}
@@ -2617,7 +2640,10 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
b_len = sizeof(b);
if (wr) {
fd = is_wr2 ? rep->out2fd : rep->outfd;
- crwp = is_wr2 ? "writing2" : "writing";
+ if (clp->verify)
+ crwp = is_wr2 ? "verifying2" : "verifying";
+ else
+ crwp = is_wr2 ? "writing2" : "writing";
} else {
fd = rep->infd;
crwp = "reading";