diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2022-02-03 02:38:23 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2022-02-03 02:38:23 +0000 |
commit | 6b32eacd43ada71e267506e510db11e8988cc7dc (patch) | |
tree | 394e5b9921dfd8bf199310581609e945f4b76e7d /src | |
parent | d5890d56b6bcb6d1aa277f0bab78abb1ef66a88e (diff) | |
download | sg3_utils-6b32eacd43ada71e267506e510db11e8988cc7dc.tar.gz |
sg_rep_zones: add --brief option and --find ZT option; sg_modes: improve handling of zbc disks with pdt=0x14
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@935 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_logs.c | 150 | ||||
-rw-r--r-- | src/sg_modes.c | 13 | ||||
-rw-r--r-- | src/sg_rep_zones.c | 295 | ||||
-rw-r--r-- | src/sg_senddiag.c | 25 |
4 files changed, 364 insertions, 119 deletions
diff --git a/src/sg_logs.c b/src/sg_logs.c index 26e1b477..2fce0b5a 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -36,7 +36,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "1.93 20220127"; /* spc6r06 + sbc5r01 */ +static const char * version_str = "1.94 20220201"; /* spc6r06 + sbc5r01 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -3112,7 +3112,7 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op) const uint8_t * bp; const char * cp; char str[PCB_STR_LEN]; - char b[256]; + char b[512]; char bb[32]; bool full, decoded; bool has_header = false; @@ -3305,8 +3305,8 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op) break; } /* end of switch statement */ if ((! decoded) && full) { - printf(" parameter code = 0x%x, contents in hex:\n", pc); - hex2stdout(bp, param_len, 1); + hex2str(bp, param_len, " ", 1 /* no ASCII */, sizeof(b), b); + printf(" parameter code = 0x%x, contents in hex:\n%s", pc, b); } else printf("\n"); if (op->do_pcb) @@ -4132,6 +4132,7 @@ show_format_status_page(const uint8_t * resp, int len, const uint8_t * xp; uint64_t ull; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Format status page [0x8]\n"); @@ -4160,8 +4161,9 @@ show_format_status_page(const uint8_t * resp, int len, if (sg_all_ffs(bp + 4, pl - 4)) printf(" Format data out: <not available>\n"); else { - printf(" Format data out:\n"); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, + sizeof(b), b); + printf(" Format data out:\n%s", b); } } is_count = false; @@ -4181,7 +4183,8 @@ show_format_status_page(const uint8_t * resp, int len, default: printf(" Unknown Format parameter code = 0x%x\n", pc); is_count = false; - hex2stdout(bp, pl, 0); + hex2str(bp, pl, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; } if (is_count) { @@ -4543,7 +4546,7 @@ show_dt_device_status_page(const uint8_t * resp, int len, int num, pl, pc, j; const uint8_t * bp; char str[PCB_STR_LEN]; - char b[64]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("DT device status page (ssc-3, adc-3) [0x11]\n"); @@ -4621,7 +4624,8 @@ show_dt_device_status_page(const uint8_t * resp, int len, pl); break; } - hex2stdout(bp + 4, 8, 1); + hex2str(bp + 4, 8, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; case 0x3: printf(" Key management error data (hex only now):\n"); @@ -4634,7 +4638,8 @@ show_dt_device_status_page(const uint8_t * resp, int len, pl); break; } - hex2stdout(bp + 4, 12, 1); + hex2str(bp + 4, 12, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; default: if ((pc >= 0x101) && (pc <= 0x1ff)) { @@ -4651,14 +4656,20 @@ show_dt_device_status_page(const uint8_t * resp, int len, sg_get_unaligned_be64(bp + 8)); } else { printf(" non-SAS transport, in hex:\n"); - hex2stdout(bp + 4, ((pl < num) ? pl : num) - 4, 0); + hex2str(bp + 4, ((pl < num) ? pl : num) - 4, " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } } else if (pc >= 0x8000) { printf(" Vendor specific [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); } else { printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); } break; } @@ -4681,6 +4692,7 @@ show_tapealert_response_page(const uint8_t * resp, int len, int num, pl, pc, k, mod, div; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("TapeAlert response page (ssc-3, adc-3) [0x12]\n"); @@ -4721,10 +4733,14 @@ show_tapealert_response_page(const uint8_t * resp, int len, default: if (pc <= 0x8000) { printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } else { printf(" Vendor specific [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } break; } @@ -4770,6 +4786,7 @@ show_requested_recovery_page(const uint8_t * resp, int len, int num, pl, pc, j, k; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Requested recovery page (ssc-3) [0x13]\n"); @@ -4805,10 +4822,14 @@ show_requested_recovery_page(const uint8_t * resp, int len, default: if (pc <= 0x8000) { printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } else { printf(" Vendor specific [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } break; } @@ -4832,6 +4853,7 @@ show_ata_pt_results_page(const uint8_t * resp, int len, const uint8_t * bp; const uint8_t * dp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("ATA pass-through results page (sat-2) [0x16]\n"); @@ -4869,11 +4891,15 @@ show_ata_pt_results_page(const uint8_t * resp, int len, printf(" device=0x%x status=0x%x\n", dp[12], dp[13]); } else if (pl > 17) { printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } else { printf(" short parameter length: %d [parameter_code=0x%x]:\n", pl, pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } if (op->do_pcb) printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str))); @@ -4921,6 +4947,7 @@ show_background_scan_results_page(const uint8_t * resp, int len, int j, m, num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Background scan results page [0x15]\n"); @@ -4987,7 +5014,9 @@ show_background_scan_results_page(const uint8_t * resp, int len, else printf(" Medium scan parameter # %d [0x%x], " "reserved\n", pc, pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; } else printf(" Medium scan parameter # %d [0x%x]\n", pc, pc); @@ -5050,6 +5079,7 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len, int num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Zoned block device statistics page [0x14,0x1]\n"); @@ -5196,7 +5226,9 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len, break; default: printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; } if (trunc) @@ -5299,6 +5331,7 @@ show_background_op_page(const uint8_t * resp, int len, int num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Background operation page [0x15,0x2]\n"); @@ -5334,7 +5367,9 @@ show_background_op_page(const uint8_t * resp, int len, break; default: printf(" Reserved [parameter_code=0x%x]:\n", pc); - hex2stdout(bp, ((pl < num) ? pl : num), 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; } if (op->do_pcb) @@ -5357,6 +5392,7 @@ show_lps_misalignment_page(const uint8_t * resp, int len, int num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("LPS misalignment page [0x15,0x3]\n"); @@ -5396,7 +5432,9 @@ show_lps_misalignment_page(const uint8_t * resp, int len, pc, bp[4]); } else { printf("<unexpected pc=0x%x>\n", pc); - hex2stdout(bp, pl, 0); + hex2str(bp, ((pl < num) ? pl : num), " ", + 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } break; } @@ -5419,6 +5457,7 @@ show_service_buffer_info_page(const uint8_t * resp, int len, int num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Service buffer information page (adc-3) [0x15]\n"); @@ -5449,11 +5488,13 @@ show_service_buffer_info_page(const uint8_t * resp, int len, } else if (pc < 0x8000) { printf(" parameter_code=0x%x, Reserved, parameter in hex:\n", pc); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } else { printf(" parameter_code=0x%x, Vendor-specific, parameter in " "hex:\n", pc); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); } if (op->do_pcb) printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str))); @@ -5588,6 +5629,7 @@ show_device_stats_page(const uint8_t * resp, int len, int num, pl, pc; const uint8_t * bp; char str[PCB_STR_LEN]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Device statistics page (ssc-3 and adc)\n"); @@ -5719,7 +5761,9 @@ show_device_stats_page(const uint8_t * resp, int len, default: vl_num = false; printf(" Reserved parameter code [0x%x] data in hex:\n", pc); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); break; } if (vl_num) @@ -5742,7 +5786,9 @@ show_device_stats_page(const uint8_t * resp, int len, "hex:\n", pc); else printf(" Reserved parameter [0x%x], dump in hex:\n", pc); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); break; } } @@ -5949,11 +5995,11 @@ static bool show_tape_diag_data_page(const uint8_t * resp, int len, const struct opts_t * op) { - int k, num, pl, pc; + int k, n, num, pl, pc; unsigned int v; const uint8_t * bp; char str[PCB_STR_LEN]; - char b[80]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Tape diagnostics data page (ssc-3) [0x16]\n"); @@ -6000,24 +6046,25 @@ show_tape_diag_data_page(const uint8_t * resp, int len, if (sg_all_zeros(bp + 32, 32)) printf(" Medium id number is 32 bytes of zero\n"); else { - printf(" Medium id number (in hex):\n"); - hex2stdout(bp + 32, 32, 0); + hex2str(bp + 32, 32, " ", 0 /* with ASCII */, sizeof(b), b); + printf(" Medium id number (in hex):\n%s", b); } printf(" Timestamp origin: 0x%x\n", bp[64] & 0xf); // Check Timestamp for all zeros - for (k = 66; k < 72; ++k) { - if(bp[k]) - break; - } - if (72 == k) + if (sg_all_zeros(bp + 66, 6)) printf(" Timestamp is all zeros:\n"); else { - printf(" Timestamp:\n"); - hex2stdout(bp + 66, 6, 1); + hex2str(bp + 66, 6, NULL, 1 /* no ASCII */, sizeof(b), b); + printf(" Timestamp: %s", b); } if (pl > 72) { + n = pl - 72; + k = hex2str(bp + 72, n, " ", 0 /* with ASCII */, + sizeof(b), b); printf(" Vendor specific:\n"); - hex2stdout(bp + 72, pl - 72, 0); + printf("%s", b); + if (k >= (int)sizeof(b) - 1) + printf(" <truncated>\n"); } if (op->do_pcb) printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str))); @@ -6039,7 +6086,7 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len, unsigned int v; const uint8_t * bp; char str[PCB_STR_LEN]; - char b[80]; + char b[512]; if (op->verbose || ((! op->do_raw) && (0 == op->do_hex))) printf("Media changer diagnostics data page (smc-3) [0x16]\n"); @@ -6104,12 +6151,16 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len, printf(" Destination address: 0x%x\n", v); if (pl > 91) { printf(" Volume tag information:\n"); - hex2stdout((bp + 56), 36, 0); + hex2str(bp + 56, 36, " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); } if (pl > 99) { printf(" Timestamp origin: 0x%x\n", bp[92] & 0xf); printf(" Timestamp:\n"); - hex2stdout((bp + 94), 6, 1); + hex2str(bp + 94, 6, " ", 1 /* no ASCII */, + sizeof(b), b); + printf("%s", b); } if (op->do_pcb) printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str))); @@ -6202,7 +6253,7 @@ show_volume_stats_pages(const uint8_t * resp, int len, bool spf; const uint8_t * bp; char str[PCB_STR_LEN]; - char b[64]; + char b[512]; spf = !!(resp[0] & 0x40); subpg_code = spf ? resp[1] : 0; @@ -6414,7 +6465,8 @@ show_volume_stats_pages(const uint8_t * resp, int len, else printf(" Reserved parameter code (0x%x), payload in hex\n", pc); - hex2stdout(bp + 4, pl - 4, 0); + hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); break; } if (op->do_pcb) @@ -6735,6 +6787,7 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op) bool spf; bool done = false; const struct log_elem * lep; + char b[512]; if (len < 3) { pr2serr("%s: response has bad length: %d\n", __func__, len); @@ -6764,12 +6817,15 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op) else printf("Unable to decode page = 0x%x, here is hex:\n", pg_code); if (len > 128) { - hex2stdout(resp, 64, 1); + hex2str(resp, 64, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); printf(" ..... [truncated after 64 of %d bytes (use '-H' to " "see the rest)]\n", len); } - else - hex2stdout(resp, len, 1); + else { + hex2str(resp, len, " ", 1 /* no ASCII */, sizeof(b), b); + printf("%s", b); + } } } diff --git a/src/sg_modes.c b/src/sg_modes.c index c0fc87f0..2eead452 100644 --- a/src/sg_modes.c +++ b/src/sg_modes.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2021 D. Gilbert + * Copyright (C) 2000-2022 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.74 20210803"; +static const char * version_str = "1.75 20220202"; #define DEF_ALLOC_LEN (1024 * 4) #define DEF_6_ALLOC_LEN 252 @@ -880,8 +880,7 @@ static const char * find_page_code_desc(int page_num, int subpage_num, int scsi_ptype, bool encserv, bool mchngr, int t_proto) { - int k; - int num; + int k, num, decayed_pdt; const struct page_code_desc * pcdp; if (t_proto >= 0) { @@ -896,6 +895,7 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype, } } } +try_again: pcdp = get_mpage_tbl_size(scsi_ptype, &num); if (pcdp) { for (k = 0; k < num; ++k, ++pcdp) { @@ -906,6 +906,11 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype, break; } } + decayed_pdt = sg_lib_pdt_decay(scsi_ptype); + if (decayed_pdt != scsi_ptype) { + scsi_ptype = decayed_pdt; + goto try_again; + } if ((0xd != scsi_ptype) && encserv) { /* check for attached enclosure services processor */ pcdp = get_mpage_tbl_size(0xd, &num); diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c index 02c8953c..c77bd785 100644 --- a/src/sg_rep_zones.c +++ b/src/sg_rep_zones.c @@ -39,11 +39,11 @@ * Based on zbc2r10.pdf */ -static const char * version_str = "1.30 20220128"; +static const char * version_str = "1.31 20220201"; #define WILD_RZONES_BUFF_LEN (1 << 28) -#define MAX_RZONES_BUFF_LEN (1024 * 1024) -#define DEF_RZONES_BUFF_LEN (1024 * 8) +#define MAX_RZONES_BUFF_LEN (2 * 1024 * 1024) +#define DEF_RZONES_BUFF_LEN (1024 * 16) #define SG_ZONING_IN_CMDLEN 16 @@ -51,6 +51,7 @@ static const char * version_str = "1.30 20220128"; #define REPORT_ZONE_DOMAINS_SA 0x7 #define REPORT_REALMS_SA 0x6 +#define REPORT_ZONES_DESC_LEN 64 #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ #define DEF_PT_TIMEOUT 60 /* 60 seconds */ @@ -69,6 +70,7 @@ struct opts_t { int do_help; int do_hex; int do_num; + int find_zt; /* negative values: find first not equal to */ int maxlen; int reporting_opt; int vb; @@ -76,12 +78,17 @@ struct opts_t { const char * in_fn; }; +struct zt_num2abbrev_t { + int ztn; + const char * abbrev; +}; static struct option long_options[] = { {"brief", no_argument, 0, 'b'}, /* only header and last descriptor */ {"domain", no_argument, 0, 'd'}, {"domains", no_argument, 0, 'd'}, {"force", no_argument, 0, 'f'}, + {"find", required_argument, 0, 'F'}, {"help", no_argument, 0, 'h'}, {"hex", no_argument, 0, 'H'}, {"in", required_argument, 0, 'i'}, /* silent, same as --inhex= */ @@ -102,22 +109,58 @@ static struct option long_options[] = { {0, 0, 0, 0}, }; +static struct zt_num2abbrev_t zt_num2abbrev[] = { + {0, "none"}, + {1, "c"}, /* conventionial */ + {2, "swr"}, /* sequential write required */ + {3, "swp"}, /* sequential write preferred */ + {4, "sobr"}, /* sequential or before required */ + {5, "g"}, /* gap */ + {-1, NULL}, /* sentinel */ +}; + +static const char * zn_dnum_s = "zone descriptor number: "; + + +static void +prn_zone_type_abbrevs(void) +{ + const struct zt_num2abbrev_t * n2ap = zt_num2abbrev; + char b[32]; + + pr2serr("Zone type number\tAbbreviation\tName\n"); + pr2serr("----------------\t------------\t----\n"); + for ( ; n2ap->abbrev; ++n2ap) { + if (n2ap == zt_num2abbrev) + pr2serr("\t%d\t\t%s\t\t[reserved]\n", + n2ap->ztn, n2ap->abbrev); + else + pr2serr("\t%d\t\t%s\t\t%s\n", n2ap->ztn, n2ap->abbrev, + sg_get_zone_type_str(n2ap->ztn, sizeof(b), b)); + } +} static void usage(int h) { if (h > 1) goto h_twoormore; pr2serr("Usage: " - "sg_rep_zones [--domain] [--force] [--help] [--hex] " - "[--inhex=FN]\n" - " [--locator=LBA] [--maxlen=LEN] " - "[--partial] [--only]\n" - " [--raw] [--readonly] [--realm] " - "[--report=OPT]\n" - " [--start=LBA] [--verbose] [--version] " - "DEVICE\n"); + "sg_rep_zones [--domain] [--find=ZT] [--force] [--help] " + "[--hex]\n" + " [--inhex=FN] [--locator=LBA] " + "[--maxlen=LEN]\n" + " [--partial] [--only] [--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" + " --find=ZT|-F ZT find first zone with ZT zone type, " + "starting at LBA\n" + " if first character of ZT is - or !, " + "find first\n" + " zone that is not ZT\n" " --force|-f bypass some sanity checks when decoding " "response\n" " --help|-h print out usage message, use twice for " @@ -186,6 +229,8 @@ h_twoormore: "Required zones\n" " 0x3 list all realms that contain active Sequential Write " "Preferred zones\n"); + pr2serr("\n"); + prn_zone_type_abbrevs(); } /* Invokes a SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT REALMS command @@ -317,18 +362,44 @@ static const char * same_desc_arr[16] = { "Reserved [0xc]", "Reserved [0xd]", "Reserved [0xe]", "Reserved [0xf]", }; +static uint64_t +prt_a_zn_desc(const uint8_t *bp, const struct opts_t * op) +{ + uint8_t zt, zc; + uint64_t lba, len, wp; + char b[80]; + + zt = bp[0] & 0xf; + zc = (bp[1] >> 4) & 0xf; + 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), op->vb)); + printf(" PUEP: %d\n", !!(bp[1] & 0x4)); /* added in zbc2r07 */ + printf(" Non_seq: %d\n", !!(bp[1] & 0x2)); + printf(" Reset: %d\n", bp[1] & 0x1); + len = sg_get_unaligned_be64(bp + 8); + printf(" Zone Length: 0x%" PRIx64 "\n", len); + lba = sg_get_unaligned_be64(bp + 16); + printf(" Zone start LBA: 0x%" PRIx64 "\n", lba); + wp = sg_get_unaligned_be64(bp + 24); + if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp))) + printf(" Write pointer LBA: -1\n"); + else + printf(" Write pointer LBA: 0x%" PRIx64 "\n", wp); + return lba + len; +} + static int decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, const struct opts_t * op) { - uint8_t zt; - int k, same, zc, num_zd; - uint64_t wp, ul, ul2, mx_lba; + int k, same, num_zd; + uint64_t wp, ul, mx_lba; const uint8_t * bp; - char b[80]; if ((uint32_t)act_len < decod_len) { - num_zd = (act_len >= 64) ? ((act_len - 64) / 64): 0; + num_zd = (act_len >= 64) ? ((act_len - 64) / REPORT_ZONES_DESC_LEN) + : 0; if (act_len == op->maxlen) { if (op->maxlen_given) pr2serr("decode length [%u bytes] may be constrained by " @@ -338,10 +409,15 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, } else if (op->in_fn) pr2serr("perhaps %s has been truncated\n", op->in_fn); } else - num_zd = (decod_len - 64) / 64; + num_zd = (decod_len - 64) / REPORT_ZONES_DESC_LEN; same = rzBuff[4] & 0xf; mx_lba = sg_get_unaligned_be64(rzBuff + 8); - if (! op->wp_only) { + if (op->wp_only) { + ; + } else if (op->do_hex) { + hex2stdout(rzBuff, 64, -1); + printf("\n"); + } else { printf(" Same=%d: %s\n", same, same_desc_arr[same]); printf(" Maximum LBA: 0x%" PRIx64 "\n\n", mx_lba); printf(" Reported zone starting LBA granularity: 0x%" PRIx64 "\n\n", @@ -349,61 +425,54 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len, } if (op->do_num > 0) num_zd = (num_zd > op->do_num) ? op->do_num : num_zd; - if (((uint32_t)act_len < decod_len) && ((num_zd * 64) + 64 > act_len)) { + if (((uint32_t)act_len < decod_len) && + ((num_zd * REPORT_ZONES_DESC_LEN) + 64 > act_len)) { pr2serr("Skip due to truncated response, try using --num= to a " "value less than %d\n", num_zd); return SG_LIB_CAT_MALFORMED; } if (op->do_brief && (num_zd > 0)) { - bp = rzBuff + 64 + ((num_zd - 1) * 64); + bp = rzBuff + 64 + ((num_zd - 1) * REPORT_ZONES_DESC_LEN); + if (op->do_hex) { + if (op->wp_only) + hex2stdout(bp + 24, 8, -1); + else + hex2stdout(bp, 64, -1); + return 0; + } printf("From last descriptor in this response:\n"); - ul = sg_get_unaligned_be64(bp + 16); - printf(" Zone start LBA: 0x%" PRIx64 "\n", ul); - ul2 = sg_get_unaligned_be64(bp + 8); - printf(" Zone Length: 0x%" PRIx64 "\n", ul2); - ul = ul + ul2; + printf(" %s%d\n", zn_dnum_s, num_zd - 1); + ul = prt_a_zn_desc(bp, op); if (ul > mx_lba) - printf(" This zone seems to be the last one\n"); + printf(" >> This zone seems to be the last one\n"); else - printf(" Probable next Zone start LBA: 0x%" PRIx64 "\n", ul); + printf(" >> Probable next Zone start LBA: 0x%" PRIx64 "\n", ul); return 0; } - for (k = 0, bp = rzBuff + 64; k < num_zd; ++k, bp += 64) { + for (k = 0, bp = rzBuff + 64; k < num_zd; + ++k, bp += REPORT_ZONES_DESC_LEN) { if (! op->wp_only) - printf(" Zone descriptor: %d\n", k); + printf(" %s%d\n", zn_dnum_s, k); if (op->do_hex) { hex2stdout(bp, 64, -1); continue; } if (op->wp_only) { - wp = sg_get_unaligned_be64(bp + 24); - if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp))) - printf("-1\n"); - else - printf("0x%" PRIx64 "\n", wp); + if (op->do_hex) + hex2stdout(bp + 24, 8, -1); + else { + wp = sg_get_unaligned_be64(bp + 24); + if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp))) + printf("-1\n"); + else + printf("0x%" PRIx64 "\n", wp); + } continue; } - zt = bp[0] & 0xf; - zc = (bp[1] >> 4) & 0xf; - 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), op->vb)); - printf(" PUEP: %d\n", !!(bp[1] & 0x4)); /* added in zbc2r07 */ - printf(" Non_seq: %d\n", !!(bp[1] & 0x2)); - printf(" Reset: %d\n", bp[1] & 0x1); - printf(" Zone Length: 0x%" PRIx64 "\n", - sg_get_unaligned_be64(bp + 8)); - printf(" Zone start LBA: 0x%" PRIx64 "\n", - sg_get_unaligned_be64(bp + 16)); - wp = sg_get_unaligned_be64(bp + 24); - if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp))) - printf(" Write pointer LBA: -1\n"); - else - printf(" Write pointer LBA: 0x%" PRIx64 "\n", wp); + prt_a_zn_desc(bp, op); } - if ((op->do_num == 0) && (! op->wp_only)) { - if ((64 + (64 * (uint32_t)num_zd)) < decod_len) + if ((op->do_num == 0) && (! op->wp_only) && (! op->do_hex)) { + if ((64 + (REPORT_ZONES_DESC_LEN * (uint32_t)num_zd)) < decod_len) printf("\n>>> Beware: Zone list truncated, may need another " "call\n"); } @@ -532,11 +601,89 @@ decode_rep_zdomains(const uint8_t * rzBuff, int act_len, return 0; } +static int +find_report_zones(int sg_fd, uint8_t * rzBuff, const char * cmd_name, + struct opts_t * op) +{ + bool found = false; + uint8_t zt; + int k, res, resid, rlen, num_zd; + uint32_t zn_dnum = 0; + uint64_t slba = op->st_lba; + uint64_t mx_lba = 0; + const uint8_t * bp = rzBuff; + char b[96]; + + k = 0; + while (true) { + resid = 0; + res = sg_ll_report_zzz(sg_fd, REPORT_ZONES_SA, slba, + true /* set partial */, op->reporting_opt, + rzBuff, op->maxlen, &resid, true, op->vb); + if (res) { + if (SG_LIB_CAT_INVALID_OP == res) + pr2serr("%s: %s%u, %s command not supported\n", __func__, + zn_dnum_s, zn_dnum, cmd_name); + else { + sg_get_category_sense_str(res, sizeof(b), b, op->vb); + pr2serr("%s: %s%u, %s command: %s\n", __func__, + zn_dnum_s, zn_dnum, cmd_name, b); + } + break; + } + rlen = op->maxlen - resid; + if (rlen <= 64) { + break; + } + mx_lba = sg_get_unaligned_be64(rzBuff + 8); + num_zd = (rlen - 64) / REPORT_ZONES_DESC_LEN; + for (k = 0, bp = rzBuff + 64; k < num_zd; + ++k, bp += REPORT_ZONES_DESC_LEN, ++zn_dnum) { + zt = 0xf & bp[0]; + if (op->find_zt > 0) { + if ((uint8_t)op->find_zt == zt ) + break; + } else if (op->find_zt < 0) { + if ((uint8_t)(-op->find_zt) != zt ) + break; + } + slba = sg_get_unaligned_be64(bp + 16) + + sg_get_unaligned_be64(bp + 8); + } + if (k < num_zd) { + found = true; + break; + } else if (slba > mx_lba) + break; + } + if (res == 0) { + if (found) { + if (op->do_hex) { + hex2stdout(rzBuff, 64, -1); + printf("\n"); + hex2stdout(bp, 64, -1); + } else { + printf("Condition met at:\n"); + printf(" %s: %d\n", zn_dnum_s, zn_dnum); + prt_a_zn_desc(bp, op); + } + } else { + if (op->do_hex) { + memset(b, 0xff, 64); + hex2stdout((const uint8_t *)b, 64, -1); + } else + printf("Condition NOT met; next %s%u\n", zn_dnum_s, zn_dnum); + } + } + return res; +} + + int main(int argc, char * argv[]) { bool no_final_msg = false; - int res, c, act_len, rlen, in_len; + int res, c, act_len, rlen, in_len, off; int sg_fd = -1; int resid = 0; int ret = 0; @@ -555,8 +702,8 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "bdefhHi:l:m:n:o:prRs:vVw", long_options, - &option_index); + c = getopt_long(argc, argv, "bdefF:hHi:l:m:n:o:prRs:vVw", + long_options, &option_index); if (c == -1) break; @@ -575,6 +722,31 @@ main(int argc, char * argv[]) case 'f': op->do_force = true; break; + case 'F': + off = (('-' == *optarg) || ('!' == *optarg)) ? 1 : 0; + if (isdigit(*(optarg + off))) { + op->find_zt = sg_get_num_nomult(optarg + off); + if (op->find_zt < 0) { + pr2serr("bad numeric argument to '--find='\n"); + return SG_LIB_SYNTAX_ERROR; + } + if (off) + op->find_zt = -op->find_zt; /* find first not equal */ + } else { /* check for abbreviation */ + struct zt_num2abbrev_t * zn2ap = zt_num2abbrev; + + for ( ; zn2ap->abbrev; ++zn2ap) { + if (0 == strcmp(optarg + off, zn2ap->abbrev)) + break; + } + if (NULL == zn2ap->abbrev) { + pr2serr("bad abbreviation argument to '--find='\n\n"); + prn_zone_type_abbrevs(); + return SG_LIB_SYNTAX_ERROR; + } + op->find_zt = off ? -zn2ap->ztn : zn2ap->ztn; + } + break; case 'h': case '?': ++op->do_help; @@ -758,6 +930,10 @@ main(int argc, char * argv[]) goto the_end; } + if (op->find_zt) { /* so '-F none' will drop through */ + ret = find_report_zones(sg_fd, rzBuff, cmd_name, op); + goto the_end; + } res = sg_ll_report_zzz(sg_fd, serv_act, op->st_lba, op->do_partial, op->reporting_opt, rzBuff, op->maxlen, &resid, true, op->vb); @@ -782,7 +958,8 @@ start_response: if ((REPORT_ZONES_SA == serv_act) && (! op->do_partial)) { printf("%u zones starting from LBA 0x%" PRIx64 " available " "but only %d zones returned\n", - (decod_len - 64) / 64, op->st_lba, (rlen - 64) / 64); + (decod_len - 64) / REPORT_ZONES_DESC_LEN, op->st_lba, + (rlen - 64) / REPORT_ZONES_DESC_LEN); decod_len = rlen; act_len = rlen; } else { @@ -806,7 +983,7 @@ start_response: hex2stdout(rzBuff, act_len, ((1 == op->do_hex) ? 1 : -1)); goto the_end; } - if (! op->wp_only) + if (! op->wp_only && (! op->do_hex)) printf("%s response:\n", cmd_name); if (act_len < 64) { pr2serr("Zone length [%d] too short (perhaps after truncation\n)", diff --git a/src/sg_senddiag.c b/src/sg_senddiag.c index 6539d79d..7e82dd47 100644 --- a/src/sg_senddiag.c +++ b/src/sg_senddiag.c @@ -1,6 +1,6 @@ /* * A utility program originally written for the Linux OS SCSI subsystem - * Copyright (C) 2003-2021 D. Gilbert + * Copyright (C) 2003-2022 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) @@ -34,7 +34,7 @@ #include "sg_pr2serr.h" -static const char * version_str = "0.64 20210610"; +static const char * version_str = "0.65 20220128"; #define ME "sg_senddiag: " @@ -836,16 +836,23 @@ main(int argc, char * argv[]) num = sg_msense_calc_length(rsp_buff, 32, false, &bd_len); num -= (8 /* MS(10) header length */ + bd_len); if (num >= 0xc) { - int secs; - - secs = sg_get_unaligned_be16(rsp_buff + 8 + bd_len + 10); + int secs = sg_get_unaligned_be16(rsp_buff + 8 + bd_len + 10); + + if (0xffff == secs) { + if (op->verbose > 1) + printf("Expected extended self-test duration's value " + "[65535] indicates the\nsimilarly named field " + "in the Extended Inquiry VPD page should be " + "used\n"); + } else { #ifdef SG_LIB_MINGW - printf("Expected extended self-test duration=%d seconds " - "(%g minutes)\n", secs, secs / 60.0); + printf("Expected extended self-test duration=%d seconds " + "(%g minutes)\n", secs, secs / 60.0); #else - printf("Expected extended self-test duration=%d seconds " - "(%.2f minutes)\n", secs, secs / 60.0); + printf("Expected extended self-test duration=%d seconds " + "(%.2f minutes)\n", secs, secs / 60.0); #endif + } } else printf("Extended self-test duration not available\n"); } else { |