aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2021-06-07 15:21:01 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2021-06-07 15:21:01 +0000
commit30363466e3580cae5f428c9bf35caa934cef469b (patch)
tree265f9bd6b4a8ebcf7102908ca0596dc1f42ce28a
parentd65eadbdaa302c7b83c059569a28efd3304947e4 (diff)
downloadsg3_utils-30363466e3580cae5f428c9bf35caa934cef469b.tar.gz
sg_vpd: fix do_hex type on some recent pages; sg_dd: don't close negative file descriptors; pt_linux_nvme: fix fua setting
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@903 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--COVERAGE4
-rw-r--r--ChangeLog9
-rw-r--r--debian/changelog2
-rw-r--r--lib/sg_cmds_basic.c8
-rw-r--r--lib/sg_pt_freebsd.c4
-rw-r--r--lib/sg_pt_linux_nvme.c8
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_dd.c12
-rw-r--r--src/sg_raw.c16
-rw-r--r--src/sg_rep_zones.c101
-rw-r--r--src/sg_vpd.c6
-rw-r--r--src/sgm_dd.c12
-rw-r--r--src/sgp_dd.c10
-rw-r--r--testing/sg_mrq_dd.cpp107
-rw-r--r--testing/sgh_dd.cpp87
-rw-r--r--testing/uapi_sg.h3
16 files changed, 233 insertions, 158 deletions
diff --git a/COVERAGE b/COVERAGE
index 7dcafa7f..3c5c9ffa 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -82,7 +82,7 @@ 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 REALMS sg_rep_zones
REPORT ZONES sg_rep_zones
REQUEST SENSE sg_requests, ++
RESET WRITE POINTER sg_reset_wp
@@ -180,4 +180,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-28th May 2021
+7th June 2021
diff --git a/ChangeLog b/ChangeLog
index 3c5bdda5..6bf0479e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,16 +2,19 @@ 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 [20210528] [svn: r902]
- - sg_rep_zones: start support for REPORT ZONE DOMAINS and
- REPORT ZONE REALMS in this utility
+Changelog for pre-release sg3_utils-1.47 [20210607] [svn: r903]
+ - sg_rep_zones: add support for REPORT ZONE DOMAINS and
+ REPORT 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_vpd: fix do_hex type on some recent pages
- sg_lib: add sg_scsi_status_is_good(),
+ - sg_dd, sgm_dd, sgp_dd: don't close negative file descriptors
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_linux_nvme: fix fua setting
- pt: check_pt_file_handle() add return value of 5 for
FreeBSD for nvme(cam)
- move some hex files from examples to inhex directory
diff --git a/debian/changelog b/debian/changelog
index fda25bee..4e993062 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.47-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Sat, 15 May 2021 17:00:00 -0400
+ -- Douglas Gilbert <dgilbert@interlog.com> Mon, 07 Jun 2021 11:00:00 -0400
sg3-utils (1.46-0.1) unstable; urgency=low
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 0b862821..d1a61168 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2020 Douglas Gilbert.
+ * Copyright (c) 1999-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.
@@ -42,7 +42,7 @@
#endif
-static const char * const version_str = "1.97 20200722";
+static const char * const version_str = "1.98 20210601";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -622,7 +622,7 @@ sg_ll_test_unit_ready_com(struct sg_pt_base * ptvp, int sg_fd, int pack_id,
bool local_cdb = true;
int res, ret, sense_cat;
uint8_t tur_cdb[TUR_CMDLEN] = {TUR_CMD, 0, 0, 0, 0, 0};
- uint8_t sense_b[SENSE_BUFF_LEN];
+ uint8_t sense_b[SENSE_BUFF_LEN] = {0};
if (verbose) {
char b[128];
@@ -748,7 +748,7 @@ sg_ll_request_sense_com(struct sg_pt_base * ptvp, int sg_fd, bool desc,
}
if (ptvp) {
ptvp_given = true;
- if (get_scsi_pt_sense_buf(ptvp))
+ if (get_scsi_pt_cdb_buf(ptvp))
local_cdb = false;
else
set_scsi_pt_cdb(ptvp, rs_cdb, sizeof(rs_cdb));
diff --git a/lib/sg_pt_freebsd.c b/lib/sg_pt_freebsd.c
index 918197c6..b6af6704 100644
--- a/lib/sg_pt_freebsd.c
+++ b/lib/sg_pt_freebsd.c
@@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-/* sg_pt_freebsd version 1.43 20210503 */
+/* sg_pt_freebsd version 1.44 20210601 */
#include <stdio.h>
#include <stdlib.h>
@@ -2514,7 +2514,7 @@ sntl_rread(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp,
bool is_read10 = (SCSI_READ10_OPC == cdbp[0]);
bool have_fua = !!(cdbp[1] & 0x8);
int err;
- uint32_t nblks_t10 = 0;
+ uint32_t nblks_t10 = 0; /* 'control' in upper 16 bits */
uint64_t lba;
struct nvme_pt_command npc;
uint8_t * npc_up = (uint8_t *)&npc;
diff --git a/lib/sg_pt_linux_nvme.c b/lib/sg_pt_linux_nvme.c
index 094dc49c..3dbd182e 100644
--- a/lib/sg_pt_linux_nvme.c
+++ b/lib/sg_pt_linux_nvme.c
@@ -41,7 +41,7 @@
* MA 02110-1301, USA.
*/
-/* sg_pt_linux_nvme version 1.17 20210501 */
+/* sg_pt_linux_nvme version 1.18 20210601 */
/* This file contains a small "SPC-only" SNTL to support the SES pass-through
* of SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS through NVME-MI
@@ -154,7 +154,7 @@
#define SG_NVME_NVM_WRITE 0x1
#define SG_NVME_NVM_WRITE_ZEROES 0x8 /* SCSI WRITE SAME */
-#define SG_NVME_RW_CDW12_FUA (1 << 30) /* Force Unit Access bit */
+#define SG_NVME_RW_CONTROL_FUA (1 << 14) /* Force Unit Access bit */
#if (HAVE_NVME && (! IGNORE_NVME))
@@ -1480,7 +1480,7 @@ sntl_rread(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
iop->nblocks = nblks_t10 - 1; /* crazy "0's based" */
if (have_fua)
- iop->nblocks |= SG_NVME_RW_CDW12_FUA;
+ iop->control |= SG_NVME_RW_CONTROL_FUA;
iop->addr = (uint64_t)ptp->io_hdr.din_xferp;
res = sntl_do_nvm_cmd(ptp, iop, ptp->io_hdr.din_xfer_len,
true /* is_read */, time_secs, vb);
@@ -1526,7 +1526,7 @@ sntl_write(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
iop->nblocks = nblks_t10 - 1;
if (have_fua)
- iop->nblocks |= SG_NVME_RW_CDW12_FUA;
+ iop->control |= SG_NVME_RW_CONTROL_FUA;
iop->addr = (uint64_t)ptp->io_hdr.dout_xferp;
res = sntl_do_nvm_cmd(ptp, iop, ptp->io_hdr.dout_xfer_len, false,
time_secs, vb);
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 67790c66..ddd80ef8 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Sat May 15 2021 - dgilbert at interlog dot com
+* Mon Jun 07 2021 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.47
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 13cfd780..4266972f 100644
--- a/src/sg_dd.c
+++ b/src/sg_dd.c
@@ -70,7 +70,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "6.26 20210512";
+static const char * version_str = "6.27 20210601";
#define ME "sg_dd: "
@@ -2479,7 +2479,7 @@ main(int argc, char * argv[])
} else if (FT_DEV_NULL & out_type)
;
else {
- off64_t offset = blocks * blk_sz;
+ off64_t offset = (off64_t)blocks * blk_sz;
off64_t off_res;
if (verbose > 2)
@@ -2681,10 +2681,12 @@ bypass_copy:
free(wrkBuff);
if (free_zeros_buff)
free(free_zeros_buff);
- if (STDIN_FILENO != infd)
+ if ((STDIN_FILENO != infd) && (infd >= 0))
close(infd);
- if (! ((STDOUT_FILENO == outfd) || (FT_DEV_NULL & out_type)))
- close(outfd);
+ if (! ((STDOUT_FILENO == outfd) || (FT_DEV_NULL & out_type))) {
+ if (outfd >= 0)
+ close(outfd);
+ }
if (dry_run > 0)
goto bypass2;
diff --git a/src/sg_raw.c b/src/sg_raw.c
index c831a172..9cfa19c3 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -39,7 +39,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.36 (2021-04-29)"
+#define SG_RAW_VERSION "0.4.37 (2021-06-01)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -300,13 +300,6 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
}
}
- if (optind >= argc) {
- pr2serr("No device specified\n");
- return SG_LIB_SYNTAX_ERROR;
- }
- op->device_name = argv[optind];
- ++optind;
-
if (op->version_given
#ifdef DEBUG
&& ! op->verbose_given
@@ -314,6 +307,13 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
)
return 0;
+ if (optind >= argc) {
+ pr2serr("No device specified\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->device_name = argv[optind];
+ ++optind;
+
while (optind < argc) {
char *opt = argv[optind++];
char *endptr;
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 7ad7a9cb..98bc2a03 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -34,11 +34,12 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
*
*
- * This program issues the SCSI REPORT ZONES command to the given SCSI device
- * and decodes the response. Based on zbc-r02.pdf
+ * This program issues the SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT
+ * REALMS command to the given SCSI device and decodes the response.
+ * Based on zbc2r10.pdf
*/
-static const char * version_str = "1.24 20210527";
+static const char * version_str = "1.25 20210602";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -46,6 +47,8 @@ static const char * version_str = "1.24 20210527";
#define SG_ZONING_IN_CMDLEN 16
#define REPORT_ZONES_SA 0x0
+#define REPORT_ZONE_DOMAINS_SA 0x7
+#define REPORT_REALMS_SA 0x6
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
#define DEF_PT_TIMEOUT 60 /* 60 seconds */
@@ -77,11 +80,11 @@ usage(int h)
if (h > 1) goto h_twoormore;
pr2serr("Usage: "
"sg_rep_zones [--domain] [--help] [--hex] [--locator=LBA]\n"
- " [--maxlen=LEN] [--partial] [--raw] "
- "[--readonly]\n"
- " [--realm] [--report=OPT] [--start=LBA] "
+ " [--maxlen=LEN] [--partial] [--raw] "
+ "[--readonly]\n"
+ " [--realm] [--report=OPT] [--start=LBA] "
"[--verbose]\n"
- " [--version] DEVICE\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 "
@@ -101,7 +104,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"
+ " --realm|-e sends a REPORT 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"
@@ -109,13 +112,13 @@ 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, 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 "
+ "Sends a SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT REALMS "
+ "command.\n By default sends a REPORT ZONES command. Give help "
+ "option twice\n(e.g. '-hh') to see reporting options "
"enumerated.\n");
return;
h_twoormore:
- pr2serr("Reporting options:\n"
+ pr2serr("Reporting options for REPORT ZONES:\n"
" 0x0 list all zones\n"
" 0x1 list zones with a zone condition of EMPTY\n"
" 0x2 list zones with a zone condition of IMPLICITLY "
@@ -131,15 +134,30 @@ h_twoormore:
" 0x11 list zones with Non-sequential write resources "
"active set to true\n"
" 0x3f list zones with a zone condition of NOT WRITE "
- "POINTER\n");
+ "POINTER\n\n");
+ pr2serr("Reporting options for REPORT ZONE DOMAINS:\n"
+ " 0x0 list all zone domains\n"
+ " 0x1 list all zone domains in which all zones are active\n"
+ " 0x2 list all zone domains that contain active zones\n"
+ " 0x3 list all zone domains that do not contain any active "
+ "zones\n\n");
+ pr2serr("Reporting options for REPORT REALMS:\n"
+ " 0x0 list all realms\n"
+ " 0x1 list all realms that contain active Sequential Or "
+ "Before Required zones\n"
+ " 0x2 list all realms that contain active Sequential Write "
+ "Required zones\n"
+ " 0x3 list all realms that contain active Sequential Write "
+ "Preferred zones\n");
}
-/* Invokes a SCSI REPORT ZONES command (ZBC). Return of 0 -> success,
- * various SG_LIB_CAT_* positive values or -1 -> other errors */
+/* Invokes a SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT REALMS command
+ * (see ZBC and ZBC-2). Return of 0 -> success, various SG_LIB_CAT_* positive
+ * values or -1 -> other errors */
static int
-sg_ll_report_zones(int sg_fd, uint64_t zs_lba, bool partial, int report_opts,
- void * resp, int mx_resp_len, int * residp, bool noisy,
- int verbose)
+sg_ll_report_zzz(int sg_fd, int serv_act, uint64_t zs_lba, bool partial,
+ int report_opts, void * resp, int mx_resp_len,
+ int * residp, bool noisy, int verbose)
{
int ret, res, sense_cat;
uint8_t rz_cdb[SG_ZONING_IN_CMDLEN] =
@@ -148,6 +166,7 @@ sg_ll_report_zones(int sg_fd, uint64_t zs_lba, bool partial, int report_opts,
uint8_t sense_b[SENSE_BUFF_LEN];
struct sg_pt_base * ptvp;
+ rz_cdb[1] = serv_act;
sg_put_unaligned_be64(zs_lba, rz_cdb + 2);
sg_put_unaligned_be32((uint32_t)mx_resp_len, rz_cdb + 10);
rz_cdb[14] = report_opts & 0x3f;
@@ -156,9 +175,8 @@ sg_ll_report_zones(int sg_fd, uint64_t zs_lba, bool partial, int report_opts,
if (verbose) {
char b[128];
- pr2serr(" Report zones cdb: %s\n",
- sg_get_command_str(rz_cdb, SG_ZONING_IN_CMDLEN, false,
- sizeof(b), b));
+ pr2serr(" %s\n", sg_get_command_str(rz_cdb, SG_ZONING_IN_CMDLEN,
+ true, sizeof(b), b));
}
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
@@ -169,8 +187,8 @@ sg_ll_report_zones(int sg_fd, uint64_t zs_lba, bool partial, int report_opts,
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "report zones", res, noisy, verbose,
- &sense_cat);
+ ret = sg_cmds_process_resp(ptvp, "report zone/domain/realm", res, noisy,
+ verbose, &sense_cat);
if (-1 == ret)
ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
else if (-2 == ret) {
@@ -266,7 +284,7 @@ main(int argc, char * argv[])
bool do_partial = false;
bool do_raw = false;
bool do_zdomains = false;
- bool do_zrealms = false;
+ bool do_realms = false;
bool o_readonly = false;
bool verbose_given = false;
bool version_given = false;
@@ -280,6 +298,7 @@ main(int argc, char * argv[])
int reporting_opt = 0;
int ret = 0;
int verbose = 0;
+ int serv_act = REPORT_ZONES_SA;
uint8_t zt;
uint64_t st_lba = 0;
uint64_t wp;
@@ -288,6 +307,7 @@ main(int argc, char * argv[])
uint8_t * reportZonesBuff = NULL;
uint8_t * free_rzbp = NULL;
uint8_t * bp;
+ const char * cmd_name = "Report zones";
char b[80];
while (1) {
@@ -300,11 +320,13 @@ main(int argc, char * argv[])
switch (c) {
case 'd':
- do_zdomains = true;
- break;
+ do_zdomains = true;
+ serv_act = REPORT_ZONE_DOMAINS_SA;
+ break;
case 'e':
- do_zrealms = true;
- break;
+ do_realms = true;
+ serv_act = REPORT_REALMS_SA;
+ break;
case 'h':
case '?':
++do_help;
@@ -312,7 +334,7 @@ main(int argc, char * argv[])
case 'H':
++do_hex;
break;
- /* case 'l': is under case 's': */
+ /* case 'l': is under case 's': */
case 'm':
maxlen = sg_get_num(optarg);
if ((maxlen < 0) || (maxlen > MAX_RZONES_BUFF_LEN)) {
@@ -346,7 +368,7 @@ main(int argc, char * argv[])
o_readonly = true;
break;
case 's':
- case 'l':
+ case 'l': /* --locator= and --start= are interchangeable */
ll = sg_get_llnum(optarg);
if (-1 == ll) {
pr2serr("bad argument to '--start=LBA' or '--locator=LBA\n");
@@ -407,9 +429,16 @@ main(int argc, char * argv[])
usage(do_help);
return 0;
}
- if (do_zdomains && do_zrealms) {
+ if (do_zdomains && do_realms) {
pr2serr("Can't have both --domain and --realm\n");
return SG_LIB_SYNTAX_ERROR;
+ } else if (do_zdomains)
+ cmd_name = "Report zone domains";
+ else if (do_realms)
+ cmd_name = "Report realms";
+ if ((serv_act != REPORT_ZONES_SA) && do_partial) {
+ pr2serr("Can only use --partial with REPORT ZONES\n");
+ return SG_LIB_SYNTAX_ERROR;
}
if (NULL == device_name) {
pr2serr("missing device name!\n");
@@ -442,7 +471,7 @@ main(int argc, char * argv[])
return sg_convert_errno(ENOMEM);
}
- res = sg_ll_report_zones(sg_fd, st_lba, do_partial, reporting_opt,
+ res = sg_ll_report_zzz(sg_fd, serv_act, st_lba, do_partial, reporting_opt,
reportZonesBuff, maxlen, &resid, true, verbose);
ret = res;
if (0 == res) {
@@ -470,7 +499,7 @@ main(int argc, char * argv[])
goto the_end;
}
if (! wp_only)
- printf("Report zones response:\n");
+ printf("%s response:\n", cmd_name);
if (len < 64) {
pr2serr("Zone length [%d] too short (perhaps after truncation\n)",
len);
@@ -500,7 +529,7 @@ main(int argc, char * argv[])
zt = bp[0] & 0xf;
zc = (bp[1] >> 4) & 0xf;
printf(" Zone type: %s\n", sg_get_zone_type_str(zt, sizeof(b),
- 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 */
@@ -522,10 +551,10 @@ main(int argc, char * argv[])
"call\n");
}
} else if (SG_LIB_CAT_INVALID_OP == res)
- pr2serr("Report zones command not supported\n");
+ pr2serr("%s command not supported\n", cmd_name);
else {
sg_get_category_sense_str(res, sizeof(b), b, verbose);
- pr2serr("Report zones command: %s\n", b);
+ pr2serr("%s command: %s\n", cmd_name, b);
}
the_end:
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 63b3afb5..4e538d6f 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.63 20210328"; /* spc6r05 + sbc4r22 */
+static const char * version_str = "1.64 20210601"; /* spc6r05 + sbc4r22 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -2654,7 +2654,7 @@ decode_b7_vpd(uint8_t * buff, int len, int do_hex, int pdt)
/* VPD_FORMAT_PRESETS 0xb8 (added sbc4r18) */
static void
-decode_format_presets_vpd(uint8_t * buff, int len, bool do_hex)
+decode_format_presets_vpd(uint8_t * buff, int len, int do_hex)
{
int k;
unsigned int sch_type;
@@ -2723,7 +2723,7 @@ decode_format_presets_vpd(uint8_t * buff, int len, bool do_hex)
/* VPD_CON_POS_RANGE 0xb9 (added sbc5r01) */
static void
-decode_con_pos_range_vpd(uint8_t * buff, int len, bool do_hex)
+decode_con_pos_range_vpd(uint8_t * buff, int len, int do_hex)
{
int k;
uint64_t u;
diff --git a/src/sgm_dd.c b/src/sgm_dd.c
index b01d694b..d4e2ce16 100644
--- a/src/sgm_dd.c
+++ b/src/sgm_dd.c
@@ -1,7 +1,7 @@
/* A utility program for copying files. Specialised for "files" that
* represent devices that understand the SCSI command set.
*
- * Copyright (C) 1999 - 2020 D. Gilbert and P. Allworth
+ * Copyright (C) 1999 - 2021 D. Gilbert and P. Allworth
* 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)
@@ -69,7 +69,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.67 20200510";
+static const char * version_str = "1.68 20210601";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -1442,10 +1442,12 @@ main(int argc, char * argv[])
fini:
if (wrkBuff)
free(wrkBuff);
- if (STDIN_FILENO != infd)
+ if ((STDIN_FILENO != infd) && (infd >= 0))
close(infd);
- if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
- close(outfd);
+ if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type)) {
+ if (outfd >= 0)
+ close(outfd);
+ }
if ((0 != dd_count) && (0 == dry_run)) {
pr2serr("Some error occurred,");
if (0 == ret)
diff --git a/src/sgp_dd.c b/src/sgp_dd.c
index cda52d3b..503df157 100644
--- a/src/sgp_dd.c
+++ b/src/sgp_dd.c
@@ -84,7 +84,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "5.77 20210103";
+static const char * version_str = "5.78 20210601";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -1911,10 +1911,12 @@ main(int argc, char * argv[])
* _join() to clear heap taken by associated _create() */
fini:
- if (STDIN_FILENO != clp->infd)
+ if ((STDIN_FILENO != clp->infd) && (clp->infd >= 0))
close(clp->infd);
- if ((STDOUT_FILENO != clp->outfd) && (FT_DEV_NULL != clp->out_type))
- close(clp->outfd);
+ if ((STDOUT_FILENO != clp->outfd) && (FT_DEV_NULL != clp->out_type)) {
+ if (clp->outfd >= 0)
+ close(clp->outfd);
+ }
res = exit_status;
if ((0 != clp->out_count) && (0 == clp->dry_run)) {
pr2serr(">>>> Some error occurred, remaining blocks=%" PRId64 "\n",
diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp
index 00296025..57382f4e 100644
--- a/testing/sg_mrq_dd.cpp
+++ b/testing/sg_mrq_dd.cpp
@@ -30,7 +30,7 @@
*
*/
-static const char * version_str = "1.29 20210515";
+static const char * version_str = "1.30 20210606";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -189,6 +189,7 @@ struct flags_t {
bool fua;
bool hipri;
bool masync; /* more async sg v4 driver fd flag */
+ bool mout_if; /* META_OUT_IF flag at mrq level */
bool nocreat;
bool no_dur;
bool no_thresh;
@@ -307,6 +308,8 @@ typedef struct request_element
int mrq_id;
int mrq_index;
int mrq_pack_id_off;
+ uint32_t a_mrq_din_blks;
+ uint32_t a_mrq_dout_blks;
int64_t in_follow_on;
int64_t out_follow_on;
int64_t in_local_count;
@@ -579,7 +582,12 @@ sg_flags_str(int flags, int b_len, char * b)
goto fini;
}
if (SGV4_FLAG_REC_ORDER & flags) { /* 0x100000 */
- n += sg_scnpr(b + n, b_len - n, "RECO|");
+ n += sg_scnpr(b + n, b_len - n, "REC_O|");
+ if (n >= b_len)
+ goto fini;
+ }
+ if (SGV4_FLAG_META_OUT_IF & flags) { /* 0x200000 */
+ n += sg_scnpr(b + n, b_len - n, "MOUT_IF|");
if (n >= b_len)
goto fini;
}
@@ -885,9 +893,9 @@ usage(int pg_num)
" if file or device to read from (def: stdin)\n"
" iflag comma separated list from: [00,coe,dio,"
"direct,dpo,\n"
- " dsync,excl,ff,fua,masync,mmap,nodur,null,"
- "order,\n"
- " qhead,qtail,random,serial,wq_excl]\n"
+ " dsync,excl,ff,fua,masync,mmap,mout_if,nodur,"
+ "null,\n"
+ " order,qhead,qtail,random,serial,wq_excl]\n"
" of file or device to write to (def: /dev/null "
"N.B. different\n"
" from dd it defaults to stdout). If 'of=.' "
@@ -985,6 +993,7 @@ page3:
" masync set 'more async' flag on this sg device\n"
" mmap setup mmap IO on IFILE or OFILE\n"
" mmap,mmap when used twice, doesn't call munmap()\n"
+ " mout_if set META_OUT_IF flag on control object\n"
" nocreat will fail rather than create OFILE\n"
" nodur turns off command duration calculations\n"
" no_thresh skip checking per fd max data xfer size\n"
@@ -1199,11 +1208,9 @@ sig_listen_thread(struct global_collection * clp)
static bool
sg_share_prepare(int write_side_fd, int read_side_fd, int id, bool vb_b)
{
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
seip->sei_rd_mask |= SG_SEIM_SHARE_FD;
seip->share_fd = read_side_fd;
@@ -1223,11 +1230,9 @@ sg_share_prepare(int write_side_fd, int read_side_fd, int id, bool vb_b)
static void
sg_take_snap(int sg_fd, int id, bool vb_b)
{
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_SNAP_DEV;
@@ -1246,7 +1251,7 @@ sg_take_snap(int sg_fd, int id, bool vb_b)
static void
read_write_thread(struct global_collection * clp, int id, bool singleton)
{
- Rq_elem rel;
+ Rq_elem rel {};
Rq_elem * rep = &rel;
int n, sz, fd, vb, err, seg_blks;
int res = 0;
@@ -1266,7 +1271,6 @@ read_write_thread(struct global_collection * clp, int id, bool singleton)
in_mmap = (in_is_sg && (clp->in_flags.mmap > 0));
out_is_sg = (FT_SG == clp->out_type);
out_mmap = (out_is_sg && (clp->out_flags.mmap > 0));
- memset(rep, 0, sizeof(Rq_elem));
rep->clp = clp;
rep->id = id;
@@ -1813,6 +1817,14 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
ok = true;
f1 = !!(a_v4p->info); /* want to skip n_subm count if info is 0x0 */
if (SG_INFO_CHECK & a_v4p->info) {
+ if ((0 == k) && (SGV4_FLAG_META_OUT_IF & ctl_v4p->flags) &&
+ (UINT32_MAX == a_v4p->info)) {
+ hole_count = 0;
+ n_good = num_mrq;
+ good_inblks = rep->a_mrq_din_blks;
+ good_outblks = rep->a_mrq_dout_blks;
+ break;
+ }
ok = false;
pr2serr_lk("[%d] a_v4[%d]: SG_INFO_CHECK set [%s]\n", id, k,
sg_info_str(a_v4p->info, sizeof(b), b));
@@ -1898,8 +1910,8 @@ sg_half_segment_mrq0(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
int num, kk, lin_blks, cdbsz, err;
uint32_t q_blks = 0;
struct global_collection * clp = rep->clp;
- cdb_arr_t t_cdb = {};
- struct sg_io_v4 t_v4;
+ cdb_arr_t t_cdb {};
+ struct sg_io_v4 t_v4 {};
struct sg_io_v4 * t_v4p = &t_v4;
struct flags_t * flagsp = is_wr ? &clp->out_flags : &clp->in_flags;
int vb = clp->verbose;
@@ -1940,7 +1952,6 @@ sg_half_segment_mrq0(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
} else if (vb > 3)
lk_print_command_len("cdb: ", t_cdb.data(), cdbsz, true);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->request = (uint64_t)t_cdb.data();
t_v4p->usr_ptr = t_v4p->request;
@@ -1951,9 +1962,11 @@ sg_half_segment_mrq0(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
if (is_wr) {
t_v4p->dout_xfer_len = num * clp->bs;
t_v4p->dout_xferp = (uint64_t)(dp + (q_blks * clp->bs));
+ t_v4p->din_xfer_len = 0;
} else {
t_v4p->din_xfer_len = num * clp->bs;
t_v4p->din_xferp = (uint64_t)(dp + (q_blks * clp->bs));
+ t_v4p->dout_xfer_len = 0;
}
t_v4p->timeout = clp->cmd_timeout;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
@@ -2005,12 +2018,12 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
uint32_t out_mrq_q_blks = 0;
const int max_cdb_sz = MAX_SCSI_CDB_SZ;
struct sg_io_v4 * a_v4p;
- struct sg_io_v4 ctl_v4; /* MRQ control object */
+ struct sg_io_v4 ctl_v4 {}; /* MRQ control object */
struct global_collection * clp = rep->clp;
const char * iosub_str = "SG_IOSUBMIT(variable blocking)";
char b[80];
- cdb_arr_t t_cdb = {};
- struct sg_io_v4 t_v4;
+ cdb_arr_t t_cdb {};
+ struct sg_io_v4 t_v4 {};
struct sg_io_v4 * t_v4p = &t_v4;
struct flags_t * flagsp = is_wr ? &clp->out_flags : &clp->in_flags;
bool serial = flagsp->serial;
@@ -2024,6 +2037,8 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
a_cdb.clear();
a_v4.clear();
+ rep->a_mrq_din_blks = 0;
+ rep->a_mrq_dout_blks = 0;
mrq_pack_id_base = id * PACK_ID_TID_MULTIPLIER;
rflags = 0;
@@ -2060,7 +2075,6 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
lk_print_command_len("cdb: ", t_cdb.data(), cdbsz, true);
a_cdb.push_back(t_cdb);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->flags = rflags;
t_v4p->request_len = cdbsz;
@@ -2069,11 +2083,15 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
t_v4p->flags = rflags;
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
if (is_wr) {
+ rep->a_mrq_dout_blks += num;
t_v4p->dout_xfer_len = num * clp->bs;
t_v4p->dout_xferp = (uint64_t)(dp + (mrq_q_blks * clp->bs));
+ t_v4p->din_xfer_len = 0;
} else {
+ rep->a_mrq_din_blks += num;
t_v4p->din_xfer_len = num * clp->bs;
t_v4p->din_xferp = (uint64_t)(dp + (mrq_q_blks * clp->bs));
+ t_v4p->dout_xfer_len = 0;
}
t_v4p->timeout = clp->cmd_timeout;
mrq_q_blks += num;
@@ -2095,7 +2113,6 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
num_mrq = a_v4.size();
a_v4p = a_v4.data();
res = 0;
- memset(&ctl_v4, 0, sizeof(ctl_v4));
ctl_v4.guard = 'Q';
ctl_v4.request_len = a_cdb.size() * max_cdb_sz;
ctl_v4.request = (uint64_t)a_cdb.data();
@@ -2106,6 +2123,11 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
ctl_v4.flags |= SGV4_FLAG_STOP_IF;
if (clp->mrq_hipri)
ctl_v4.flags |= SGV4_FLAG_HIPRI;
+ if (clp->in_flags.mout_if || clp->out_flags.mout_if) {
+ ctl_v4.flags |= SGV4_FLAG_META_OUT_IF;
+ if (num_mrq > 0)
+ a_v4[0].info = UINT32_MAX;
+ }
ctl_v4.dout_xferp = (uint64_t)a_v4.data(); /* request array */
ctl_v4.dout_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
ctl_v4.din_xferp = (uint64_t)a_v4.data(); /* response array */
@@ -2427,8 +2449,8 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
uint32_t out_fin_blks = 0;
struct global_collection * clp = rep->clp;
int vb = clp->verbose;
- cdb_arr_t t_cdb = {};
- struct sg_io_v4 t_v4;
+ cdb_arr_t t_cdb {};
+ struct sg_io_v4 t_v4 {};
struct sg_io_v4 * t_v4p = &t_v4;
struct flags_t * iflagsp = &clp->in_flags;
struct flags_t * oflagsp = &clp->out_flags;
@@ -2486,7 +2508,6 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
} else if (vb > 3)
lk_print_command_len("input cdb: ", t_cdb.data(), cdbsz, true);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->request = (uint64_t)t_cdb.data();
t_v4p->usr_ptr = t_v4p->request;
@@ -2495,6 +2516,7 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->flags = iflags;
t_v4p->request_len = cdbsz;
t_v4p->din_xfer_len = num * clp->bs;
+ t_v4p->dout_xfer_len = 0;
t_v4p->timeout = clp->cmd_timeout;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
clp->most_recent_pack_id.store(t_v4p->request_extra);
@@ -2537,7 +2559,6 @@ mrq0_again:
} else if (vb > 3)
lk_print_command_len("output cdb: ", t_cdb.data(), cdbsz, true);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->request = (uint64_t)t_cdb.data();
t_v4p->usr_ptr = t_v4p->request;
@@ -2545,6 +2566,7 @@ mrq0_again:
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->flags = oflags;
t_v4p->request_len = cdbsz;
+ t_v4p->din_xfer_len = 0;
t_v4p->dout_xfer_len = num * clp->bs;
t_v4p->timeout = clp->cmd_timeout;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
@@ -2600,12 +2622,12 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
uint32_t out_mrq_q_blks = 0;
const int max_cdb_sz = MAX_SCSI_CDB_SZ;
struct sg_io_v4 * a_v4p;
- struct sg_io_v4 ctl_v4; /* MRQ control object */
+ struct sg_io_v4 ctl_v4 {}; /* MRQ control object */
struct global_collection * clp = rep->clp;
const char * iosub_str = "SG_IOSUBMIT(svb)";
char b[80];
- cdb_arr_t t_cdb = {};
- struct sg_io_v4 t_v4;
+ cdb_arr_t t_cdb {};
+ struct sg_io_v4 t_v4 {};
struct sg_io_v4 * t_v4p = &t_v4;
struct flags_t * iflagsp = &clp->in_flags;
struct flags_t * oflagsp = &clp->out_flags;
@@ -2616,6 +2638,8 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
a_cdb.clear();
a_v4.clear();
+ rep->a_mrq_din_blks = 0;
+ rep->a_mrq_dout_blks = 0;
mrq_pack_id_base = id * PACK_ID_TID_MULTIPLIER;
iflags = SGV4_FLAG_SHARE;
@@ -2668,7 +2692,6 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
lk_print_command_len("input cdb: ", t_cdb.data(), cdbsz, true);
a_cdb.push_back(t_cdb);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->flags = iflags;
t_v4p->request_len = cdbsz;
@@ -2676,6 +2699,8 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
t_v4p->din_xfer_len = num * clp->bs;
+ rep->a_mrq_din_blks += num;
+ t_v4p->dout_xfer_len = 0;
t_v4p->timeout = clp->cmd_timeout;
in_mrq_q_blks += num;
t_v4p->request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
@@ -2694,14 +2719,15 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
} else if (vb > 3)
lk_print_command_len("output cdb: ", t_cdb.data(), cdbsz, true);
a_cdb.push_back(t_cdb);
- memset(t_v4p, 0, sizeof(*t_v4p));
t_v4p->guard = 'Q';
t_v4p->flags = oflags;
t_v4p->request_len = cdbsz;
t_v4p->response = (uint64_t)rep->sb;
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
+ t_v4p->din_xfer_len = 0;
t_v4p->dout_xfer_len = num * clp->bs;
+ rep->a_mrq_dout_blks += num;
t_v4p->timeout = clp->cmd_timeout;
out_mrq_q_blks += num;
t_v4p->request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
@@ -2728,7 +2754,6 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
num_mrq = a_v4.size();
a_v4p = a_v4.data();
res = 0;
- memset(&ctl_v4, 0, sizeof(ctl_v4));
ctl_v4.guard = 'Q';
ctl_v4.request_len = a_cdb.size() * max_cdb_sz;
ctl_v4.request = (uint64_t)a_cdb.data();
@@ -2741,6 +2766,11 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
ctl_v4.flags |= SGV4_FLAG_ORDERED_WR;
if (clp->mrq_hipri)
ctl_v4.flags |= SGV4_FLAG_HIPRI;
+ if (clp->in_flags.mout_if || clp->out_flags.mout_if) {
+ ctl_v4.flags |= SGV4_FLAG_META_OUT_IF;
+ if (num_mrq > 0)
+ a_v4[0].info = UINT32_MAX;
+ }
ctl_v4.dout_xferp = (uint64_t)a_v4.data(); /* request array */
ctl_v4.dout_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
ctl_v4.din_xferp = (uint64_t)a_v4.data(); /* response array */
@@ -2851,10 +2881,9 @@ static int
sg_blk_poll(int fd, int num)
{
int res;
- struct sg_extended_info sei;
+ struct sg_extended_info sei {};
struct sg_extended_info * seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_rd_mask |= SG_SEIM_BLK_POLL;
seip->sei_wr_mask |= SG_SEIM_BLK_POLL;
seip->num = (num < 0) ? 0 : num;
@@ -2882,7 +2911,7 @@ sg_prepare_resbuf(int fd, struct global_collection *clp, bool is_in,
int elem_sz = clp->elem_sz;
int res, t, num, err;
uint8_t *mmp;
- struct sg_extended_info sei;
+ struct sg_extended_info sei {};
struct sg_extended_info * seip = &sei;
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
@@ -2899,14 +2928,12 @@ sg_prepare_resbuf(int fd, struct global_collection *clp, bool is_in,
goto bypass;
}
if (elem_sz >= 4096) {
- memset(seip, 0, sizeof(*seip));
seip->sei_rd_mask |= SG_SEIM_SGAT_ELEM_SZ;
res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
if (res < 0)
pr2serr_lk("sg_mrq_dd: %s: SG_SET_GET_EXTENDED(SGAT_ELEM_SZ) rd "
"error: %s\n", __func__, strerror(errno));
if (elem_sz != (int)seip->sgat_elem_sz) {
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SGAT_ELEM_SZ;
seip->sgat_elem_sz = elem_sz;
res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
@@ -2916,7 +2943,6 @@ sg_prepare_resbuf(int fd, struct global_collection *clp, bool is_in,
}
}
if (no_dur || masync || skip_thresh) {
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
if (no_dur) {
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_NO_DURATION;
@@ -2975,7 +3001,6 @@ bypass:
if (res < 0)
perror("sg_mrq_dd: SG_SET_FORCE_PACK_ID error");
if (clp->unit_nanosec) {
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS;
seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
@@ -3146,6 +3171,8 @@ process_flags(const char * arg, struct flags_t * fp)
fp->qtail = true;
else if (0 == strcmp(cp, "random"))
fp->random = true;
+ else if ((0 == strcmp(cp, "mout_if")) || (0 == strcmp(cp, "mout-if")))
+ fp->mout_if = true;
else if (0 == strcmp(cp, "serial"))
fp->serial = true;
else if (0 == strcmp(cp, "swait"))
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 62c6a3e0..57158892 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -36,7 +36,7 @@
* renamed [20181221]
*/
-static const char * version_str = "2.08 20210515";
+static const char * version_str = "2.09 20210605";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -196,6 +196,7 @@ struct flags_t {
bool qhead;
bool qtail;
bool random;
+ bool mout_if; /* META_OUT_IF flag at mrq level */
bool same_fds;
bool swait; /* now ignore; kept for backward compatibility */
bool v3;
@@ -612,7 +613,12 @@ sg_flags_str(int flags, int b_len, char * b)
goto fini;
}
if (SGV4_FLAG_REC_ORDER & flags) { /* 0x100000 */
- n += sg_scnpr(b + n, b_len - n, "RECO|");
+ n += sg_scnpr(b + n, b_len - n, "REC_O|");
+ if (n >= b_len)
+ goto fini;
+ }
+ if (SGV4_FLAG_META_OUT_IF & flags) { /* 0x200000 */
+ n += sg_scnpr(b + n, b_len - n, "MOUT_IF|");
if (n >= b_len)
goto fini;
}
@@ -935,11 +941,11 @@ usage(int pg_num)
" if file or device to read from (def: stdin)\n"
" iflag comma separated list from: [00,coe,defres,dio,"
"direct,dpo,\n"
- " dsync,excl,ff,fua,hipri,masync,mmap,mrq_immed,"
- "mrq_svb,\n"
- " nocreat,nodur,noxfer,null,qhead,qtail,"
- "random,\n"
- " same_fds,v3,v4,wq_excl]\n"
+ " dsync,excl,ff,fua,hipri,masync,mmap,mout_if,"
+ "mrq_immed,\n"
+ " mrq_svb,nocreat,nodur,noxfer,null,qhead,"
+ "qtail,\n"
+ " random,same_fds,v3,v4,wq_excl]\n"
" of file or device to write to (def: /dev/null "
"N.B. different\n"
" from dd it defaults to stdout). If 'of=.' "
@@ -1050,6 +1056,7 @@ page3:
" mmap setup mmap IO on IFILE or OFILE; OFILE only "
"with noshare\n"
" mmap,mmap when used twice, doesn't call munmap()\n"
+ " mout_if set META_OUT_IF flag on each request\n"
" mrq_immed if mrq active, do submit non-blocking (def: "
"ordered\n"
" blocking)\n"
@@ -1308,7 +1315,7 @@ mrq_abort_thread(void * v_maip)
int seed;
unsigned int rn;
Mrq_abort_info l_mai = *(Mrq_abort_info *)v_maip;
- struct sg_io_v4 ctl_v4;
+ struct sg_io_v4 ctl_v4 {};
#ifdef HAVE_GETRANDOM
{
@@ -1347,7 +1354,6 @@ mrq_abort_thread(void * v_maip)
pr2serr_lk("%s: skipping nanosleep cause delay < 20 usecs\n",
__func__);
- memset(&ctl_v4, 0, sizeof(ctl_v4));
ctl_v4.guard = 'Q';
ctl_v4.flags = SGV4_FLAG_MULTIPLE_REQS;
ctl_v4.request_extra = l_mai.mrq_id;
@@ -1374,11 +1380,9 @@ mrq_abort_thread(void * v_maip)
static bool
sg_share_prepare(int write_side_fd, int read_side_fd, int id, bool vb_b)
{
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
seip->sei_rd_mask |= SG_SEIM_SHARE_FD;
seip->share_fd = read_side_fd;
@@ -1398,11 +1402,9 @@ sg_share_prepare(int write_side_fd, int read_side_fd, int id, bool vb_b)
static void
sg_unshare(int sg_fd, int id, bool vb_b)
{
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_UNSHARE;
@@ -1420,11 +1422,9 @@ static void
sg_noshare_enlarge(int sg_fd, bool vb_b)
{
if (sg_version_ge_40045) {
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
sei.sei_wr_mask |= SG_SEIM_TOT_FD_THRESH;
seip->tot_fd_thresh = 96 * 1024 * 1024;
if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
@@ -1440,11 +1440,9 @@ sg_noshare_enlarge(int sg_fd, bool vb_b)
static void
sg_take_snap(int sg_fd, int id, bool vb_b)
{
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_SNAP_DEV;
@@ -1507,7 +1505,7 @@ read_write_thread(void * v_tip)
{
Thread_info * tip;
struct global_collection * clp;
- Rq_elem rel;
+ Rq_elem rel {};
Rq_elem * rep = &rel;
int n, sz, blocks, status, vb, err, res, wr_blks;
int num_sg = 0;
@@ -1528,7 +1526,6 @@ read_write_thread(void * v_tip)
in_mmap = (in_is_sg && (clp->in_flags.mmap > 0));
out_is_sg = (FT_SG == clp->out_type);
out_mmap = (out_is_sg && (clp->out_flags.mmap > 0));
- memset(rep, 0, sizeof(Rq_elem));
/* Following clp members are constant during lifetime of thread */
rep->clp = clp;
rep->id = tip->id;
@@ -2153,13 +2150,12 @@ sg_wr_swap_share(Rq_elem * rep, int to_fd, bool before)
int k;
int read_side_fd = rep->infd;
struct global_collection * clp = rep->clp;
- struct sg_extended_info sei;
+ struct sg_extended_info sei {};
struct sg_extended_info * seip = &sei;
if (rep->clp->verbose > 2)
pr2serr_lk("%s: tid=%d: to_fd=%d, before=%d\n", __func__, rep->id,
to_fd, (int)before);
- memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CHG_SHARE_FD;
seip->sei_rd_mask |= SG_SEIM_CHG_SHARE_FD;
seip->share_fd = to_fd;
@@ -2205,11 +2201,10 @@ sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2, bool prefetch)
struct global_collection * clp = rep->clp;
uint32_t ofsplit = clp->ofsplit;
pthread_mutex_t * mutexp = is_wr2 ? &clp->out2_mutex : &clp->out_mutex;
- struct sg_io_extra xtr;
+ struct sg_io_extra xtr {};
struct sg_io_extra * xtrp = &xtr;
const char * wr_or_ver = clp->verify ? "verify" : "out";
- memset(xtrp, 0, sizeof(*xtrp));
xtrp->is_wr2 = is_wr2;
xtrp->prefetch = prefetch;
nblks = rep->num_blks;
@@ -2423,6 +2418,7 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
}
}
if (slen > 0) {
+pr2serr(">>>>>>>>>>>> %s: slen=%d\n", __func__, slen);
struct sg_scsi_sense_hdr ssh;
const uint8_t *sbp = (const uint8_t *)
(sb_in_co ? ctl_v4p->response : a_v4p->response);
@@ -2826,7 +2822,7 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
uint32_t in_fin_blks, out_fin_blks;
const int max_cdb_sz = 16;
struct sg_io_v4 * a_v4p;
- struct sg_io_v4 ctl_v4;
+ struct sg_io_v4 ctl_v4 {};
uint8_t * cmd_ap = NULL;
struct global_collection * clp = rep->clp;
const char * iosub_str = "iosub_str";
@@ -2834,7 +2830,6 @@ sgh_do_deferred_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
id = rep->id;
b_len = sizeof(b);
- memset(&ctl_v4, 0, sizeof(ctl_v4));
ctl_v4.guard = 'Q';
a_v4p = def_arr.first.data();
nrq = def_arr.first.size();
@@ -3121,6 +3116,7 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
bool qhead = wr ? clp->out_flags.qhead : clp->in_flags.qhead;
bool qtail = wr ? clp->out_flags.qtail : clp->in_flags.qtail;
bool hipri = wr ? clp->out_flags.hipri : clp->in_flags.hipri;
+ bool mout_if = wr ? clp->out_flags.mout_if : clp->in_flags.mout_if;
bool prefetch = xtrp ? xtrp->prefetch : false;
bool is_wr2 = xtrp ? xtrp->is_wr2 : false;
int cdbsz = wr ? clp->cdbsz_out : clp->cdbsz_in;
@@ -3185,6 +3181,8 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
flags |= SG_FLAG_Q_AT_HEAD;
if (qtail)
flags |= SG_FLAG_Q_AT_TAIL;
+ if (mout_if)
+ flags |= SGV4_FLAG_META_OUT_IF;
if (rep->has_share) {
flags |= SGV4_FLAG_SHARE;
if (wr)
@@ -3416,6 +3414,7 @@ sg_finish_io(bool wr, Rq_elem * rep, int pack_id, struct sg_io_extra *xtrp)
{
struct global_collection * clp = rep->clp;
bool v4 = wr ? clp->out_flags.v4 : clp->in_flags.v4;
+ bool mout_if = wr ? clp->out_flags.mout_if : clp->in_flags.mout_if;
bool is_wr2 = xtrp ? xtrp->is_wr2 : false;
bool prefetch = xtrp ? xtrp->prefetch : false;
int res, fd;
@@ -3514,6 +3513,11 @@ do_v4:
}
h4p = &rep->io_hdr4[xtrp ? xtrp->hpv4_ind : 0];
h4p->request_extra = pack_id;
+ if (mout_if) {
+ h4p->info = 0;
+ h4p->din_resid = 0;
+ }
+pr2serr(">>>>> %s: h4p->response: %sNULL, max_slen=%d\n", __func__, h4p->response ? "non-" : "", h4p->max_response_len);
while (((res = ioctl(fd, SG_IORECEIVE, h4p)) < 0) &&
((EINTR == errno) || (EAGAIN == errno) || (EBUSY == errno))) {
if (EAGAIN == errno) {
@@ -3535,6 +3539,11 @@ do_v4:
perror("finishing io [SG_IORECEIVE] on sg device, error");
return -1;
}
+pr2serr(">>>>> %s: h4p->response_len=%d\n", __func__, h4p->response_len);
+ if (mout_if && (0 == h4p->info) && (0 == h4p->din_resid)) {
+pr2serr("%s: META_OUT_IF set plus info and resid are zero, skip\n", __func__);
+ goto all_good;
+ }
if (rep != (Rq_elem *)h4p->usr_ptr)
err_exit(0, "sg_finish_io: bad usr_ptr, request-response mismatch\n");
res = sg_err_category_new(h4p->device_status, h4p->transport_status,
@@ -3591,6 +3600,7 @@ do_v4:
!!(h4p->info & SG_INFO_DEVICE_DETACHING),
!!(h4p->info & SG_INFO_ABORTED));
}
+all_good:
return 0;
}
@@ -3608,10 +3618,9 @@ sg_prepare_resbuf(int fd, bool is_in, struct global_collection *clp,
clp->out_flags.no_thresh;
int res, t, num;
uint8_t *mmp;
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
+ struct sg_extended_info sei {};
+ struct sg_extended_info * seip = &sei;
- seip = &sei;
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
if ((res < 0) || (t < 40000)) {
if (ioctl(fd, SG_GET_RESERVED_SIZE, &num) < 0) {
@@ -3629,7 +3638,6 @@ sg_prepare_resbuf(int fd, bool is_in, struct global_collection *clp,
if (! sg_version_ge_40045)
goto bypass;
if (clp->elem_sz >= 4096) {
- memset(seip, 0, sizeof(*seip));
seip->sei_rd_mask |= SG_SEIM_SGAT_ELEM_SZ;
res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
if (res < 0)
@@ -3815,6 +3823,8 @@ process_flags(const char * arg, struct flags_t * fp)
fp->qtail = true;
else if (0 == strcmp(cp, "random"))
fp->random = true;
+ else if ((0 == strcmp(cp, "mout_if")) || (0 == strcmp(cp, "mout-if")))
+ fp->mout_if = true;
else if (0 == strcmp(cp, "same_fds"))
fp->same_fds = true;
else if (0 == strcmp(cp, "swait"))
@@ -4390,7 +4400,7 @@ main(int argc, char * argv[])
const char * ccp = NULL;
const char * cc2p;
struct global_collection * clp = &gcoll;
- Thread_info thread_arr[MAX_NUM_THREADS];
+ Thread_info thread_arr[MAX_NUM_THREADS] {};
char ebuff[EBUFF_SZ];
#if SG_LIB_ANDROID
struct sigaction actions;
@@ -4403,7 +4413,6 @@ main(int argc, char * argv[])
sigaction(SIGUSR2, &actions, NULL);
#endif
/* memset(clp, 0, sizeof(*clp)); */
- memset(thread_arr, 0, sizeof(thread_arr));
clp->bpt = DEF_BLOCKS_PER_TRANSFER;
clp->cmd_timeout = DEF_TIMEOUT;
clp->in_type = FT_OTHER;
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index 22ed1e1a..270ad468 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -14,7 +14,7 @@
* Later extensions (versions 2, 3 and 4) to driver:
* Copyright (C) 1998 - 2021 Douglas Gilbert
*
- * Version 4.0.46 (20210111)
+ * Version 4.0.47 (20210605)
* This version is for Linux 4 and 5 series kernels.
*
* Documentation
@@ -129,6 +129,7 @@ typedef struct sg_io_hdr {
#define SGV4_FLAG_MULTIPLE_REQS 0x40000 /* 1 or more sg_io_v4-s in data-in */
#define SGV4_FLAG_ORDERED_WR 0x80000 /* svb: issue in-order writes */
#define SGV4_FLAG_REC_ORDER 0x100000 /* receive order in v4:request_priority */
+#define SGV4_FLAG_META_OUT_IF 0x200000 /* ... there is something to report */
/* Output (potentially OR-ed together) in v3::info or v4::info field */
#define SG_INFO_OK_MASK 0x1