aboutsummaryrefslogtreecommitdiff
path: root/src/sg_get_lba_status.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2017-09-13 03:21:14 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2017-09-13 03:21:14 +0000
commit3e3bb389c5718f595a07cd0a51ccd0162713f44f (patch)
tree970e512680be80718af7369e64f1b375fecff6e1 /src/sg_get_lba_status.c
parentb8ac77b23171336c1ba3ef2bd82acbaee79463fb (diff)
downloadsg3_utils-3e3bb389c5718f595a07cd0a51ccd0162713f44f.tar.gz
sync up to spc5r16 and sbc4r14
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@714 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src/sg_get_lba_status.c')
-rw-r--r--src/sg_get_lba_status.c181
1 files changed, 156 insertions, 25 deletions
diff --git a/src/sg_get_lba_status.c b/src/sg_get_lba_status.c
index 010822de..ceb9e324 100644
--- a/src/sg_get_lba_status.c
+++ b/src/sg_get_lba_status.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2016 Douglas Gilbert.
+ * Copyright (c) 2009-2017 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.
@@ -30,7 +30,11 @@
* device.
*/
-static const char * version_str = "1.08 20160423";
+static const char * version_str = "1.09 20170912";
+
+#ifndef UINT32_MAX
+#define UINT32_MAX ((uint32_t)-1)
+#endif
#define MAX_GLBAS_BUFF_LEN (1024 * 1024)
#define DEF_GLBAS_BUFF_LEN 24
@@ -40,13 +44,21 @@ static unsigned char * glbasBuffp = glbasBuff;
static struct option long_options[] = {
+ {"16", no_argument, 0, 'S'},
+ {"32", no_argument, 0, 'T'},
{"brief", no_argument, 0, 'b'},
+ {"element-id", required_argument, 0, 'e'},
+ {"element_id", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"lba", required_argument, 0, 'l'},
{"maxlen", required_argument, 0, 'm'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
+ {"report-type", required_argument, 0, 't'},
+ {"report_type", required_argument, 0, 't'},
+ {"scan-len", required_argument, 0, 's'},
+ {"scan_len", required_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
@@ -55,16 +67,23 @@ static struct option long_options[] = {
static void
usage()
{
- pr2serr("Usage: sg_get_lba_status [--brief] [--help] [--hex] "
- "[--lba=LBA]\n"
- " [--maxlen=LEN] [--raw] [--readonly] "
- "[--verbose]\n"
- " [--version] DEVICE\n"
+ pr2serr("Usage: sg_get_lba_status [--16] [--32][--brief] "
+ "[--element-id=EI]\n"
+ " [--help] [--hex] "
+ "[--lba=LBA] [--maxlen=LEN]\n"
+ " [--raw] [--readonly] "
+ "[--report-type=RT]\n"
+ " [--scan-len=SL] [--verbose] "
+ "[--version] DEVICE\n"
" where:\n"
- " --brief|-b a descriptor per line: "
- "<lba_hex blocks_hex p_status>\n"
+ " --16|-S use GET LBA STATUS(16) cdb (def)\n"
+ " --32|-T use GET LBA STATUS(32) cdb\n"
+ " --brief|-b a descriptor per line:\n"
+ " <lba_hex blocks_hex p_status "
+ "add_status>\n"
" use twice ('-bb') for given LBA "
"provisioning status\n"
+ " --element-id=EI|-e EI EI is the element identifier\n"
" --help|-h print out usage message\n"
" --hex|-H output in hexadecimal\n"
" --lba=LBA|-l LBA starting LBA (logical block address) "
@@ -75,9 +94,20 @@ usage()
DEF_GLBAS_BUFF_LEN );
pr2serr(" --raw|-r output in binary\n"
" --readonly|-R open DEVICE read-only (def: read-write)\n"
+ " --report-type=RT|-t RT report type: 0->all LBAs (def);\n"
+ " 1-> LBAs with non-zero "
+ "provisioning status\n"
+ " 2-> LBAs that are mapped\n"
+ " 3-> LBAs that are deallocated\n"
+ " 4-> LBAs that are anchored\n"
+ " 5-> LBAs that may return "
+ "unrecovered error\n"
+ " --scan-len=SL|-s SL SL in maximum scan length "
+ "(unit: logical blocks)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
- "Performs a SCSI GET LBA STATUS command (SBC-3)\n"
+ "Performs a SCSI GET LBA STATUS(16) or GET LBA STATUS(32) "
+ "command\n(SBC-3 and SBC-4)\n"
);
}
@@ -95,7 +125,7 @@ dStrRaw(const char* str, int len)
*/
static int
decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
- uint32_t * blocksp)
+ uint32_t * blocksp, uint8_t * add_statusp)
{
uint32_t blocks;
uint64_t ull;
@@ -108,6 +138,8 @@ decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
*slbap = ull;
if (blocksp)
*blocksp = blocks;
+ if (add_statusp)
+ *add_statusp = bp[13];
return bp[12] & 0xf;
}
@@ -115,25 +147,31 @@ decode_lba_status_desc(const unsigned char * bp, uint64_t * slbap,
int
main(int argc, char * argv[])
{
- int sg_fd, k, j, res, c, rlen, num_descs;
+ int sg_fd, k, j, res, c, rlen, num_descs, completion_cond;
int do_brief = 0;
int do_hex = 0;
int64_t ll;
uint64_t lba = 0;
uint64_t d_lba = 0;
uint32_t d_blocks = 0;
+ uint32_t element_id = 0;
+ uint32_t scan_len = 0;
int maxlen = DEF_GLBAS_BUFF_LEN;
int do_raw = 0;
int o_readonly = 0;
+ int rt = 0;
int verbose = 0;
+ bool do_16 = false;
+ bool do_32 = false;
const char * device_name = NULL;
const unsigned char * bp;
int ret = 0;
+ uint8_t add_status;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "bhHl:m:rRvV", long_options,
+ c = getopt_long(argc, argv, "be:hHl:m:rRs:St:TvV", long_options,
&option_index);
if (c == -1)
break;
@@ -142,6 +180,14 @@ main(int argc, char * argv[])
case 'b':
++do_brief;
break;
+ case 'e':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--element-id'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ element_id = (uint32_t)ll;
+ break;
case 'h':
case '?':
usage();
@@ -171,6 +217,28 @@ main(int argc, char * argv[])
case 'R':
++o_readonly;
break;
+ case 's':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--scan-len'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ scan_len = (uint32_t)ll;
+ break;
+ case 'S':
+ do_16 = true;
+ break;
+ case 't':
+ rt = sg_get_num_nomult(optarg);
+ if ((rt < 0) || (rt > 255)) {
+ pr2serr("'--report-type=RT' should be between 0 and 255 "
+ "(inclusive)\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
+ case 'T':
+ do_32 = true;
+ break;
case 'v':
++verbose;
break;
@@ -195,7 +263,6 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
-
if (NULL == device_name) {
pr2serr("missing device name!\n");
usage();
@@ -215,7 +282,20 @@ main(int argc, char * argv[])
goto free_buff;
}
}
-
+ if (do_16 && do_32) {
+ pr2serr("both --16 and --32 given, choose --16\n");
+ do_32 = false;
+ } else if ((! do_16) && (! do_32)) {
+ if (verbose > 3)
+ pr2serr("choosing --16\n");
+ do_16 = true;
+ }
+ if (do_16) {
+ if (element_id != 0)
+ pr2serr("Warning: --element_id= ignored with 16 byte cdb\n");
+ if (scan_len != 0)
+ pr2serr("Warning: --scan_len= ignored with 16 byte cdb\n");
+ }
sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
pr2serr("open error: %s: %s\n", device_name, safe_strerror(-sg_fd));
@@ -223,8 +303,13 @@ main(int argc, char * argv[])
goto free_buff;
}
- res = sg_ll_get_lba_status(sg_fd, lba, glbasBuffp, maxlen, 1,
- verbose);
+ if (do_16)
+ res = sg_ll_get_lba_status16(sg_fd, lba, rt, glbasBuffp, maxlen, 1,
+ verbose);
+ else
+ res = sg_ll_get_lba_status32(sg_fd, lba, element_id, scan_len, rt,
+ glbasBuffp, maxlen, 1, verbose);
+
ret = res;
if (0 == res) {
/* in sbc3r25 offset for calculating the 'parameter data length'
@@ -264,7 +349,8 @@ main(int argc, char * argv[])
ret = SG_LIB_CAT_OTHER;
goto the_end;
}
- res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks);
+ res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks,
+ &add_status);
if ((res < 0) || (res > 15)) {
pr2serr("first LBA status descriptor returned %d ??\n", res);
ret = SG_LIB_CAT_OTHER;
@@ -275,8 +361,9 @@ main(int argc, char * argv[])
" descriptor LBA: 0x");
for (j = 0; j < 8; ++j)
pr2serr("%02x", glbasBuffp[8 + j]);
- pr2serr(" blocks: 0x%x p_status: %d\n",
- (unsigned int)d_blocks, res);
+ pr2serr(" blocks: 0x%x p_status: %d add_status: 0x%x\n",
+ (unsigned int)d_blocks, res,
+ (unsigned int)add_status);
ret = SG_LIB_CAT_OTHER;
goto the_end;
}
@@ -289,10 +376,37 @@ main(int argc, char * argv[])
goto the_end;
}
num_descs = (rlen - 8) / 16;
+ completion_cond = (*(glbasBuffp + 7) >> 1) & 7; /* added sbc4r14 */
+ if (do_brief)
+ printf("Completion condition=%d\n", completion_cond);
+ else {
+ switch (completion_cond) {
+ case 0:
+ printf("No indication of the completion condition\n");
+ break;
+ case 1:
+ printf("Command completed due to meeting allocation length "
+ "(--maxlen=LEN (def 24))\n");
+ break;
+ case 2:
+ printf("Command completed due to meeting scan length "
+ "(--scan-len=SL)\n");
+ break;
+ case 3:
+ printf("Command completed due to meeting capacity of "
+ "medium\n");
+ break;
+ default:
+ printf("Command completion is reserved [%d]\n",
+ completion_cond);
+ break;
+ }
+ }
+ printf("RTP=%d\n", *(glbasBuffp + 7) & 0x1); /* added sbc4r12 */
if (verbose)
pr2serr("%d complete LBA status descriptors found\n", num_descs);
for (bp = glbasBuffp + 8, k = 0; k < num_descs; bp += 16, ++k) {
- res = decode_lba_status_desc(bp, &d_lba, &d_blocks);
+ res = decode_lba_status_desc(bp, &d_lba, &d_blocks, &add_status);
if ((res < 0) || (res > 15))
pr2serr("descriptor %d: bad LBA status descriptor returned "
"%d\n", k + 1, res);
@@ -308,16 +422,33 @@ main(int argc, char * argv[])
printf(" blocks: %u", (unsigned int)d_blocks);
switch (res) {
case 0:
- printf(" mapped (or unknown)\n");
+ printf(" mapped (or unknown)");
break;
case 1:
- printf(" deallocated\n");
+ printf(" deallocated");
break;
case 2:
- printf(" anchored\n");
+ printf(" anchored");
+ break;
+ case 3:
+ printf(" mapped"); /* sbc4r12 */
+ break;
+ case 4:
+ printf(" unknown"); /* sbc4r12 */
+ break;
+ default:
+ printf(" Provisioning status: %d", res);
+ break;
+ }
+ switch (add_status) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ printf(" [may return unrecovered errors]\n");
break;
default:
- printf(" Provisioning status: %d\n", res);
+ printf(" [add_status: 0x%x]\n", (unsigned int)add_status);
break;
}
}