aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COVERAGE4
-rw-r--r--ChangeLog8
-rw-r--r--include/sg_lib.h5
-rw-r--r--lib/sg_lib.c29
-rw-r--r--lib/sg_lib_data.c4
-rw-r--r--src/sg_inq.c2
-rw-r--r--src/sg_rep_zones.c87
-rw-r--r--src/sg_vpd.c34
8 files changed, 111 insertions, 62 deletions
diff --git a/COVERAGE b/COVERAGE
index 9a3df8b0..7dcafa7f 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -81,6 +81,8 @@ REPORT SUPPORTED OPERATION CODES sg_opcodes
REPORT SUPPORTED TASK MANAGEMENT FUNCTIONS sg_opcodes
REPORT TARGET PORT GROUPS sg_rtpg, sg_stpg ++
REPORT TIMESTAMP sg_timestamp
+REPORT ZONE DOMAINS sg_rep_zones
+REPORT ZONE_REALMS sg_rep_zones
REPORT ZONES sg_rep_zones
REQUEST SENSE sg_requests, ++
RESET WRITE POINTER sg_reset_wp
@@ -178,4 +180,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-23rd January 2021
+28th May 2021
diff --git a/ChangeLog b/ChangeLog
index c48fc583..3c5bdda5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,12 +2,14 @@ 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 pre-release sg3_utils-1.47 [20210515] [svn: r901]
+Changelog for pre-release sg3_utils-1.47 [20210528] [svn: r902]
+ - sg_rep_zones: start support for REPORT ZONE DOMAINS and
+ REPORT ZONE REALMS in this utility
- sg_raw: fix prints of NVMe NVM command names
- sg_ses: fix Windows problem "No command (cdb) given"
- sg_logs: additions to Volume statistics lpage [ssc5r05c]
- - sg_lib: add sg_scsi_status_is_good() and
- sg_scsi_status_is_bad()
+ - sg_lib: add sg_scsi_status_is_good(),
+ sg_scsi_status_is_bad() and sg_get_zone_type_str()
- pt_linux: fix verify(BytChk=0) which Linux SNTL translated
to write, other SNTL cleanups
- pt: check_pt_file_handle() add return value of 5 for
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 108ab873..857f0d1c 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -325,6 +325,11 @@ const char * sg_get_desig_code_set_str(int val);
* otherwise returns NULL. */
const char * sg_get_desig_assoc_str(int val);
+/* Yield string associated with zone type (see ZBC and ZBC-2) [e.g. REPORT
+ * ZONES command response]. Returns 'buff' unless buff_len < 1 in which
+ * NULL is returned. */
+char * sg_get_zone_type_str(uint8_t zt, int buff_len, char * buff);
+
/* Yield SCSI Feature Set (sfs) string. When 'peri_type' is < -1 (or > 31)
* returns pointer to string (same as 'buff') associated with 'sfs_code'.
* When 'peri_type' is between -1 (for SPC) and 31 (inclusive) then a match
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 3e66e13a..8b898c16 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -852,6 +852,35 @@ sg_get_desig_type_str(int val)
return NULL;
}
+char *
+sg_get_zone_type_str(uint8_t zt, int buff_len, char * buff)
+{
+ if ((NULL == buff) || (buff_len < 1))
+ return NULL;
+ switch (zt) {
+ case 1:
+ sg_scnpr(buff, buff_len, "conventional");
+ break;
+ case 2:
+ sg_scnpr(buff, buff_len, "sequential write required");
+ break;
+ case 3:
+ sg_scnpr(buff, buff_len, "sequential write preferred");
+ break;
+ case 4:
+ sg_scnpr(buff, buff_len, "sequential or before required");
+ break;
+ case 5:
+ sg_scnpr(buff, buff_len, "gap");
+ break;
+ default:
+ sg_scnpr(buff, buff_len, "unknown [0x%x]", zt);
+ break;
+ }
+ return buff;
+}
+
+
/* Expects a T10 UUID designator (as found in the Device Identification VPD
* page) pointed to by 'dp'. To not produce an error string in 'b', c_set
* should be 1 (binary) and dlen should be 18. Currently T10 only supports
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index f8bcd67e..ff89ac79 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -19,8 +19,8 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.80 20210419";
-/* spc6r05, sbc4r22, zbc2r09 */
+const char * sg_lib_version_str = "2.81 20210526";
+/* spc6r05, sbc5r01, zbc2r10 */
/* indexed by pdt; those that map to own index do not decay */
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 7977cf66..6bbeb991 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -109,7 +109,7 @@ static const char * version_str = "2.11 20210430"; /* spc6r05 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
-#define VPD_CON_POS_RANGE 0xb9 /* 20-089r2 */
+#define VPD_CON_POS_RANGE 0xb9 /* sbc5r01 */
#ifndef SG_NVME_VPD_NICR
#define SG_NVME_VPD_NICR 0xde
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 9842c9cb..7ad7a9cb 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020 Douglas Gilbert.
+ * Copyright (c) 2014-2021 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -38,7 +38,7 @@
* and decodes the response. Based on zbc-r02.pdf
*/
-static const char * version_str = "1.23 20201216";
+static const char * version_str = "1.24 20210527";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -52,13 +52,16 @@ static const char * version_str = "1.23 20201216";
static struct option long_options[] = {
+ {"domain", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
+ {"locator", required_argument, 0, 'l'},
{"maxlen", required_argument, 0, 'm'},
{"num", required_argument, 0, 'n'},
{"partial", no_argument, 0, 'p'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
+ {"realm", no_argument, 0, 'e'},
{"report", required_argument, 0, 'o'},
{"start", required_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
@@ -73,16 +76,20 @@ usage(int h)
{
if (h > 1) goto h_twoormore;
pr2serr("Usage: "
- "sg_rep_zones [--help] [--hex] [--maxlen=LEN] [--partial]\n"
- " [--raw] [--readonly] [--report=OPT] "
- "[--start=LBA]\n"
- " [--verbose] [--version] DEVICE\n");
+ "sg_rep_zones [--domain] [--help] [--hex] [--locator=LBA]\n"
+ " [--maxlen=LEN] [--partial] [--raw] "
+ "[--readonly]\n"
+ " [--realm] [--report=OPT] [--start=LBA] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n");
pr2serr(" where:\n"
+ " --domain|-d sends a REPORT ZONE DOMAINS command\n"
" --help|-h print out usage message, use twice for "
"more help\n"
" --hex|-H output response in hexadecimal; used "
"twice\n"
" shows decoded values in hex\n"
+ " --locator=LBA|-l LBA similar to --start= option\n"
" --maxlen=LEN|-m LEN max response length (allocation "
"length in cdb)\n"
" (def: 0 -> 8192 bytes)\n"
@@ -94,6 +101,7 @@ usage(int h)
"in cdb)\n"
" --raw|-r output response in binary\n"
" --readonly|-R open DEVICE read-only (def: read-write)\n"
+ " --realm|-e sends a REPORT ZONE REALMS command\n"
" --report=OPT|-o OP reporting options (def: 0: all "
"zones)\n"
" --start=LBA|-s LBA report zones from the LBA (def: 0)\n"
@@ -101,8 +109,9 @@ usage(int h)
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n"
" --wp|-w output write pointer only\n\n"
- "Sends a SCSI REPORT ZONES command and decodes the response. "
- "Give\nhelp option twice (e.g. '-hh') to see reporting options "
+ "Sends a SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT ZONE "
+ "REALMS\ncommand. By default sends a REPORT ZONES command. Give "
+ "help option twice\n(e.g. '-hh') to see reporting options "
"enumerated.\n");
return;
h_twoormore:
@@ -192,43 +201,6 @@ dStrRaw(const uint8_t * str, int len)
}
static const char *
-zone_type_str(int zt, char * b, int blen, int vb)
-{
- const char * cp;
-
- if (NULL == b)
- return "zone_type_str: NULL ptr)";
- switch (zt) {
- case 1:
- cp = "Conventional";
- break;
- case 2:
- cp = "Sequential write required";
- break;
- case 3:
- cp = "Sequential write preferred";
- break;
- case 4:
- cp = "Sequential or before required";
- break;
- case 5:
- cp = "Gap";
- break;
- default:
- cp = NULL;
- break;
- }
- if (cp) {
- if (vb)
- snprintf(b, blen, "%s [0x%x]", cp, zt);
- else
- snprintf(b, blen, "%s", cp);
- } else
- snprintf(b, blen, "Reserved [0x%x]", zt);
- return b;
-}
-
-static const char *
zone_condition_str(int zc, char * b, int blen, int vb)
{
const char * cp;
@@ -293,11 +265,13 @@ main(int argc, char * argv[])
{
bool do_partial = false;
bool do_raw = false;
+ bool do_zdomains = false;
+ bool do_zrealms = false;
bool o_readonly = false;
bool verbose_given = false;
bool version_given = false;
bool wp_only = false;
- int k, res, c, zl_len, len, zones, resid, rlen, zt, zc, same;
+ int k, res, c, zl_len, len, zones, resid, rlen, zc, same;
int sg_fd = -1;
int do_help = 0;
int do_hex = 0;
@@ -306,6 +280,7 @@ main(int argc, char * argv[])
int reporting_opt = 0;
int ret = 0;
int verbose = 0;
+ uint8_t zt;
uint64_t st_lba = 0;
uint64_t wp;
int64_t ll;
@@ -318,12 +293,18 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hHm:n:o:prRs:vVw", long_options,
+ c = getopt_long(argc, argv, "dehHl:m:n:o:prRs:vVw", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case 'd':
+ do_zdomains = true;
+ break;
+ case 'e':
+ do_zrealms = true;
+ break;
case 'h':
case '?':
++do_help;
@@ -331,6 +312,7 @@ main(int argc, char * argv[])
case 'H':
++do_hex;
break;
+ /* case 'l': is under case 's': */
case 'm':
maxlen = sg_get_num(optarg);
if ((maxlen < 0) || (maxlen > MAX_RZONES_BUFF_LEN)) {
@@ -364,9 +346,10 @@ main(int argc, char * argv[])
o_readonly = true;
break;
case 's':
+ case 'l':
ll = sg_get_llnum(optarg);
if (-1 == ll) {
- pr2serr("bad argument to '--start=LBA'\n");
+ pr2serr("bad argument to '--start=LBA' or '--locator=LBA\n");
return SG_LIB_SYNTAX_ERROR;
}
st_lba = (uint64_t)ll;
@@ -424,6 +407,10 @@ main(int argc, char * argv[])
usage(do_help);
return 0;
}
+ if (do_zdomains && do_zrealms) {
+ pr2serr("Can't have both --domain and --realm\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
if (NULL == device_name) {
pr2serr("missing device name!\n");
usage(1);
@@ -512,8 +499,8 @@ main(int argc, char * argv[])
}
zt = bp[0] & 0xf;
zc = (bp[1] >> 4) & 0xf;
- printf(" Zone type: %s\n", zone_type_str(zt, b, sizeof(b),
- verbose));
+ printf(" Zone type: %s\n", sg_get_zone_type_str(zt, sizeof(b),
+ b));
printf(" Zone condition: %s\n", zone_condition_str(zc, b,
sizeof(b), verbose));
printf(" PUEP: %d\n", !!(bp[1] & 0x4)); /* added in zbc2r07 */
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 7d2099b9..63b3afb5 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -79,7 +79,7 @@ static const char * version_str = "1.63 20210328"; /* spc6r05 + sbc4r22 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
-#define VPD_CON_POS_RANGE 0xb9 /* 20-089r2 */
+#define VPD_CON_POS_RANGE 0xb9 /* sbc5r01 */
#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
@@ -2111,7 +2111,10 @@ static const char * product_type_arr[] =
"Universal Flash Storage Card (UFS)",
};
-static const char * zoned_strs[] = {
+/* ZONED field here replaced by ZONED BLOCK DEVICE EXTENSION field in the
+ * Zoned Block Device Characteristics VPD page. The new field includes
+ * Zone Domains and Realms (see ZBC-2) */
+static const char * bdc_zoned_strs[] = {
"",
" [host-aware]",
" [host-managed]",
@@ -2184,8 +2187,9 @@ decode_b1_vpd(uint8_t * buff, int len, int do_hex, int pdt)
printf(": reserved\n");
break;
}
- zoned = (buff[8] >> 4) & 0x3; /* added sbc4r04 */
- printf(" ZONED=%d%s\n", zoned, zoned_strs[zoned]);
+ printf(" MACT=%d\n", !!(buff[8] & 0x40)); /* added sbc5r01 */
+ zoned = (buff[8] >> 4) & 0x3; /* added sbc4r04, obsolete sbc5r01 */
+ printf(" ZONED=%d%s\n", zoned, bdc_zoned_strs[zoned]);
printf(" RBWZ=%d\n", !!(buff[8] & 0x8)); /* sbc4r12 */
printf(" BOCS=%d\n", !!(buff[8] & 0x4)); /* sbc4r07 */
printf(" FUAB=%d\n", !!(buff[8] & 0x2));
@@ -2683,6 +2687,8 @@ decode_format_presets_vpd(uint8_t * buff, int len, bool do_hex)
printf(" Defines zones for host aware device:\n");
else if (3 == sch_type)
printf(" Defines zones for host managed device:\n");
+ else if (4 == sch_type)
+ printf(" Defines zones for zone domains and realms device:\n");
if ((2 == sch_type) || (3 == sch_type)) {
unsigned int u = bp[40 + 0];
@@ -2693,11 +2699,29 @@ decode_format_presets_vpd(uint8_t * buff, int len, bool do_hex)
"%u.%u %%\n", u / 10, u % 10);
printf(" logical blocks per zone: %u\n",
sg_get_unaligned_be32(bp + 40 + 12));
+ } else if (4 == sch_type) {
+ uint8_t u;
+ char b[128];
+
+ u = bp[40 + 0];
+ printf(" zone type for zone domain 0: %s\n",
+ sg_get_zone_type_str((u >> 4) & 0xf, sizeof(b), b));
+ printf(" zone type for zone domain 1: %s\n",
+ sg_get_zone_type_str(u & 0xf, sizeof(b), b));
+ u = bp[40 + 1];
+ printf(" zone type for zone domain 2: %s\n",
+ sg_get_zone_type_str((u >> 4) & 0xf, sizeof(b), b));
+ printf(" zone type for zone domain 3: %s\n",
+ sg_get_zone_type_str(u & 0xf, sizeof(b), b));
+ printf(" logical blocks per zone: %u\n",
+ sg_get_unaligned_be32(bp + 40 + 12));
+ printf(" designed zone maximum address: 0x%" PRIx64 "\n",
+ sg_get_unaligned_be64(bp + 40 + 16));
}
}
}
-/* VPD_CON_POS_RANGE 0xb9 (added 20-089r2) */
+/* VPD_CON_POS_RANGE 0xb9 (added sbc5r01) */
static void
decode_con_pos_range_vpd(uint8_t * buff, int len, bool do_hex)
{