diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2017-09-13 03:21:14 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2017-09-13 03:21:14 +0000 |
commit | 3e3bb389c5718f595a07cd0a51ccd0162713f44f (patch) | |
tree | 970e512680be80718af7369e64f1b375fecff6e1 /src/sg_get_lba_status.c | |
parent | b8ac77b23171336c1ba3ef2bd82acbaee79463fb (diff) | |
download | sg3_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.c | 181 |
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; } } |