aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--doc/sg_opcodes.825
-rw-r--r--doc/sg_rep_zones.810
-rw-r--r--include/sg_lib.h5
-rw-r--r--lib/sg_lib_data.c11
-rw-r--r--src/sg_opcodes.c63
-rw-r--r--testing/sg_mrq_dd.cpp90
-rw-r--r--testing/sgh_dd.cpp14
8 files changed, 148 insertions, 74 deletions
diff --git a/ChangeLog b/ChangeLog
index 4aeb74f1..85772d3b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ 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 released sg3_utils-1.46 [20210301] [svn: r878]
+Changelog for released sg3_utils-1.46 [20210320] [svn: r879]
- sg_rep_pip: new utility: report provisioning initialization
pattern command
- sg_turs: estimated time-to-ready [20-061r2]
@@ -20,6 +20,7 @@ Changelog for released sg3_utils-1.46 [20210301] [svn: r878]
- sg_write_x: add dld bits to write(32) [sbc4r19a]
- sg_rep_zones: print invalid write pointer LBA as -1 rather
than 16 "f"s
+ - sg_opcodes: improve handling of RWCDLP field
- sg_ses: use fan speed factor field for calculation [ses4r04]
- add --all (-a) option, same action as --join
- sg_compare_and_write: add examples section to its manpage
@@ -37,6 +38,7 @@ Changelog for released sg3_utils-1.46 [20210301] [svn: r878]
thus fix for regression introduced in rev 731 (ver: 1.43)
- sg_pt_solaris+sg_pt_osf1: fix problem with clear_scsi_pt_obj()
which needs to remember is_nvme and dev_fd values
+ - sg_lib: add ZBC (2020) feature set entries
- sg_lib: restore elements and rebuild command added
- sg_lib,sg_pt: add partial_clear_scsi_pt_obj(),
get_scsi_pt_cdb_len() and get_scsi_pt_cdb_buf()
diff --git a/doc/sg_opcodes.8 b/doc/sg_opcodes.8
index 93a9508c..cff8684a 100644
--- a/doc/sg_opcodes.8
+++ b/doc/sg_opcodes.8
@@ -1,13 +1,13 @@
-.TH SG_OPCODES "8" "June 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_OPCODES "8" "March 2020" "sg3_utils\-1.46" SG3_UTILS
.SH NAME
sg_opcodes \- report supported SCSI commands or task management functions
.SH SYNOPSIS
.B sg_opcodes
[\fI\-\-alpha\fR] [\fI\-\-compact\fR] [\fI\-\-enumerate\fR] [\fI\-\-help\fR]
[\fI\-\-hex\fR] [\fI\-\-mask\fR] [\fI\-\-mlu\fR] [\fI\-\-no-inquiry\fR]
-[\fI\-\-opcode=OP\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR] [\fI\-\-rctd\fR]
-[\fI\-\-repd\fR] [\fI\-\-sa=SA\fR] [\fI\-\-tmf\fR] [\fI\-\-unsorted\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-opcode=OP[,SA]\fR] [\fI\-\-pdt=DT\fR] [\fI\-\-raw\fR]
+[\fI\-\-rctd\fR] [\fI\-\-repd\fR] [\fI\-\-sa=SA\fR] [\fI\-\-tmf\fR]
+[\fI\-\-unsorted\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_opcodes
[\fI\-a\fR] [\fI\-c\fR] [\fI\-e\fR] [\fI\-H\fR] [\fI\-m\fR] [\fI\-M\fR]
@@ -105,12 +105,17 @@ is given then that summary is not printed on stdout.
\fB\-O\fR, \fB\-\-old\fR
Switch to older style options. Please use as first option.
.TP
-\fB\-o\fR, \fB\-\-opcode\fR=\fIOP\fR
+\fB\-o\fR, \fB\-\-opcode\fR=\fIOP[,SA]\fR
the \fIDEVICE\fR will be queried for the given operation code (i.e. the
-\fIOP\fR value) which is the first byte of a SCSI command. \fIOP\fR is
-decimal unless prefixed by "0x" or it has a trailing "h". \fIOP\fR should
-be in the range 0 to 255 (0xff) inclusive. When this option is not given
-then all available SCSI commands supported by the \fIDEVICE\fR are listed.
+\fIOP\fR value) which is the first byte of a SCSI command. Optionally, if
+a \fISA\fR value is given, it will be used as that SCSI command's service
+action. Note that \fIOP\fR and \fIOP,0\fR are not the same thing, as SCSI
+does allow the service action to be 0 (but it is not comman). \fIOP\fR and
+\fISA\fR are decimal unless prefixed by "0x" or they have a trailing "h".
+\fIOP\fR should be in the range 0 to 255 (0xff) inclusive. \fISA\fR should
+be in the range 0 to 65535 (0xffff) inclusive. When this option is not
+given then all available SCSI commands supported by the \fIDEVICE\fR are
+listed.
.TP
\fB\-p\fR, \fB\-\-pdt\fR=\fIDT\fR
where \fIDT\fR is the peripheral device type. This is used together with
@@ -304,7 +309,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2018 Douglas Gilbert
+Copyright \(co 2004\-2021 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_rep_zones.8 b/doc/sg_rep_zones.8
index cf810799..7d9c9a5d 100644
--- a/doc/sg_rep_zones.8
+++ b/doc/sg_rep_zones.8
@@ -1,12 +1,12 @@
-.TH SG_REP_ZONES "8" "June 2020" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_REP_ZONES "8" "March 2021" "sg3_utils\-1.46" SG3_UTILS
.SH NAME
sg_rep_zones \- send SCSI REPORT ZONES command
.SH SYNOPSIS
.B sg_rep_zones
[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-num=NUM\fR]
-[\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-report=OPT\fR]
-[\fI\-\-start=LBA\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wp\fR]
-\fIDEVICE\fR
+[\fI\-\-partial\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR]
+[\fI\-\-report=OPT\fR] [\fI\-\-start=LBA\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] [\fI\-\-wp\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -82,7 +82,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2014\-2020 Douglas Gilbert
+Copyright \(co 2014\-2021 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 1ece717f..e5bcc3b5 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -2,7 +2,7 @@
#define SG_LIB_H
/*
- * Copyright (c) 2004-2019 Douglas Gilbert.
+ * Copyright (c) 2004-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.
@@ -117,6 +117,9 @@ extern "C" {
#define SCSI_FS_SBC_BASE_2016 0x101
#define SCSI_FS_SBC_BASIC_PROV_2016 0x103
#define SCSI_FS_SBC_DRIVE_MAINT_2016 0x104
+#define SCSI_FS_ZBC_HOST_AWARE_2020 0x300
+#define SCSI_FS_ZBC_HOST_MANAGED_2020 0x301
+#define SCSI_FS_ZBC_DOMAINS_REALMS_2020 0x302
/* Often SCSI responses use the highest integer that can fit in a field
* to indicate "unbounded" or limit does not apply. Sometimes represented
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index cd83f7dc..2a308b8d 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2020 Douglas Gilbert.
+ * Copyright (c) 2007-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.
@@ -19,8 +19,8 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.78 20201214";
-/* spc6r02, sbc4r20a, zbc2r04 */
+const char * sg_lib_version_str = "2.79 20210304";
+/* spc6r03, sbc4r20a, zbc2r04 */
/* indexed by pdt; those that map to own index do not decay */
@@ -1057,7 +1057,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x38,0x04,"Esn - media class event"},
{0x38,0x06,"Esn - device busy class event"},
{0x38,0x07,"Thin provisioning soft threshold reached"},
- {0x38,0x08,"Depopulation interrupted"}, /* > spc6r02 */
+ {0x38,0x08,"Depopulation interrupted"}, /* spc6r03 */
{0x39,0x00,"Saving parameters not supported"},
{0x3A,0x00,"Medium not present"},
{0x3A,0x01,"Medium not present - tray closed"},
@@ -1538,6 +1538,9 @@ struct sg_lib_value_name_t sg_lib_scsi_feature_sets[] =
{SCSI_FS_SBC_BASE_2016, PDT_DISK, "SBC Base 2016"},
{SCSI_FS_SBC_BASIC_PROV_2016, PDT_DISK, "Basic provisioning 2016"},
{SCSI_FS_SBC_DRIVE_MAINT_2016, PDT_DISK, "Drive maintenance 2016"},
+ {SCSI_FS_ZBC_HOST_AWARE_2020, PDT_ZBC, "Host Aware 2020"},
+ {SCSI_FS_ZBC_HOST_MANAGED_2020, PDT_ZBC, "Host Managed 2020"},
+ {SCSI_FS_ZBC_DOMAINS_REALMS_2020, PDT_ZBC, "Domains and Realms 2020"},
{0x0, 0, NULL}, /* 0x0 is reserved sfs; trailing sentinel */
};
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 6f160ff8..57b92968 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2004-2020 D. Gilbert
+ * Copyright (C) 2004-2021 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)
@@ -33,7 +33,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.68 20200111"; /* spc6r01 */
+static const char * version_str = "0.69 20210319"; /* spc6r05 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -125,12 +125,8 @@ usage()
"all listed\n"
" --mlu|-M show MLU bit when all listed\n"
" --no-inquiry|-n don't output INQUIRY information\n"
- " --opcode=OP|-o OP first byte of command to query\n"
- " (decimal, prefix with '0x' for hex)\n"
- " --opcode=OP,SA|-o OP,SA opcode (OP) and service action "
- "(SA)\n"
- " (decimal, each prefix with '0x' for "
- "hex)\n"
+ " --opcode=OP[,SA]|-o OP[,SA] opcode (OP) and service "
+ "action (SA)\n"
" --pdt=DT|-p DT give peripheral device type for "
"'--no-inquiry'\n"
" '--enumerate'\n"
@@ -140,7 +136,6 @@ usage()
" --repd|-q set Report Extended Parameter Data bit, "
"with --tmf\n"
" --sa=SA|-s SA service action in addition to opcode\n"
- " (decimal, prefix with '0x' for hex)\n"
" --tmf|-t output list of supported task management "
"functions\n"
" --unsorted|-u output list of operation codes as is\n"
@@ -150,7 +145,9 @@ usage()
" --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
"Performs a SCSI REPORT SUPPORTED OPERATION CODES or a REPORT "
- "SUPPORTED\nTASK MANAGEMENT FUNCTIONS command.\n");
+ "SUPPORTED\nTASK MANAGEMENT FUNCTIONS command. All values are "
+ "in decimal by default,\nprefix with '0x' or add a trailing 'h' "
+ "for hex numbers.\n");
}
static void
@@ -701,12 +698,12 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op,
printf( " (hex) \n");
printf("---------------------------------------\n");
} else if (op->do_mlu) {
- printf("\nOpcode Service CDB CDLP, Name\n");
- printf( "(hex) action(h) size MLU \n");
+ printf("\nOpcode Service CDB MLU Name\n");
+ printf( "(hex) action(h) size \n");
printf("-----------------------------------------------\n");
} else {
- printf("\nOpcode Service CDB CDLP Name\n");
- printf( "(hex) action(h) size \n");
+ printf("\nOpcode Service CDB RWCDLP, Name\n");
+ printf( "(hex) action(h) size CDLP \n");
printf("-----------------------------------------------\n");
}
}
@@ -775,19 +772,21 @@ list_all_codes(uint8_t * rsoc_buff, int rsoc_len, struct opts_t * op,
"%s\n", opcode, sa_buff,
sg_get_unaligned_be16(bp + 6), name_buff);
} else { /* RCTD clear in cdb */
- /* treat RWCDLP (1 bit) and CDLP (2 bits) as a 3 bit field */
- int cdl_mp = ((byt5 >> 2) & 0x3) + ((0x40 & byt5) ? 4 : 0);
+ /* before version 0.69 treated RWCDLP (1 bit) and CDLP (2 bits),
+ * as a 3 bit field, now break them out separately */
+ int rwcdlp = (byt5 >> 2) & 0x3;
+ int cdlp = !!(0x40 & byt5);
if (op->do_compact)
printf(" %.2x%c%.4s %s\n", bp[0], (sa_v ? ',' : ' '),
sa_buff, name_buff);
else if (op->do_mlu)
- printf(" %.2x %.4s %3d %2d,%d %s\n", bp[0],
+ printf(" %.2x %.4s %3d %3d %s\n", bp[0],
sa_buff, sg_get_unaligned_be16(bp + 6),
- cdl_mp, ((byt5 >> 4) & 0x3), name_buff);
+ ((byt5 >> 4) & 0x3), name_buff);
else
- printf(" %.2x %.4s %3d %2d %s\n", bp[0],
- sa_buff, sg_get_unaligned_be16(bp + 6), cdl_mp,
+ printf(" %.2x %.4s %3d %d,%d %s\n", bp[0],
+ sa_buff, sg_get_unaligned_be16(bp + 6), rwcdlp, cdlp,
name_buff);
}
if (op->do_mask) {
@@ -859,7 +858,7 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts,
struct opts_t * op)
{
bool valid = false;
- int k, mlu;
+ int k, mlu, rwcdlp;
uint8_t * bp;
const char * cp;
const char * dlp;
@@ -898,21 +897,32 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts,
break;
}
k = 0x3 & (rsoc_buff[1] >> 3);
+ rwcdlp = rsoc_buff[0] & 1;
switch (k) { /* CDLP field */
case 0:
- dlp = "no command duration limit mode page";
+ if (rwcdlp)
+ dlp = "Reserved [RWCDLP=1, CDLP=0]";
+ else
+ dlp = "No command duration limit mode page";
break;
case 1:
- dlp = "command duration limit A mode page";
+ if (rwcdlp)
+ dlp = "Command duration limit T2A mode page";
+ else
+ dlp = "Command duration limit A mode page";
break;
case 2:
- dlp = "command duration limit B mode page";
+ if (rwcdlp)
+ dlp = "Command duration limit T2B mode page";
+ else
+ dlp = "Command duration limit B mode page";
break;
default:
dlp = "reserved [CDLP=3]";
break;
}
- printf(" Command is %s, [%s]\n", cp, dlp);
+ printf(" Command is %s\n", cp);
+ printf(" %s\n", dlp);
mlu = 0x3 & (rsoc_buff[1] >> 5);
switch (mlu) {
case 0:
@@ -1128,6 +1138,9 @@ open_rw: /* if not already open */
if (res) {
sg_get_category_sense_str(res, sizeof(b), b, vb);
pr2serr("%s: %s\n", op_name, b);
+ if ((0 == op->servact) && (op->opcode >= 0))
+ pr2serr(" >> perhaps try again without a service action "
+ "[SA] of 0\n");
goto err_out;
}
act_len = (rq_len < act_len) ? rq_len : act_len;
diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp
index 21232057..fd2bb62c 100644
--- a/testing/sg_mrq_dd.cpp
+++ b/testing/sg_mrq_dd.cpp
@@ -30,7 +30,7 @@
*
*/
-static const char * version_str = "1.20 20210210";
+static const char * version_str = "1.21 20210314";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -256,6 +256,7 @@ struct global_collection /* one instance visible to all threads */
bool processed;
bool cdbsz_given;
bool count_given;
+ bool ese;
bool flexible;
bool mrq_hipri;
bool ofile_given;
@@ -278,6 +279,7 @@ typedef struct request_element
bool only_in_sg;
bool only_out_sg;
bool stop_after_write;
+ bool stop_now;
int id;
int infd;
int outfd;
@@ -377,7 +379,6 @@ static int do_time = 1;
static struct global_collection gcoll;
static struct timeval start_tm;
static int num_threads = DEF_NUM_THREADS;
-static int exit_status = 0;
static bool after1 = false;
static const char * my_name = "sg_mrq_dd: ";
@@ -451,6 +452,18 @@ hex2stderr_lk(const uint8_t * b_str, int len, int no_ascii)
hex2stderr(b_str, len, no_ascii);
}
+static int
+system_wrapper(const char * cmd)
+{
+ int res;
+
+ res = system(cmd);
+ if (WIFSIGNALED(res) &&
+ (WTERMSIG(res) == SIGINT || WTERMSIG(res) == SIGQUIT))
+ raise(WTERMSIG(res));
+ return WEXITSTATUS(res);
+}
+
/* Flags decoded into abbreviations for those that are set, separated by
* '|' . */
static char *
@@ -844,13 +857,13 @@ usage(int pg_num)
"[--version]\n\n");
pr2serr(" [bpt=BPT] [cdbsz=6|10|12|16] [dio=0|1] "
"[elemsz_kb=EKB]\n"
- " [fua=0|1|2|3] [hipri=NRQS] [mrq=NRQS] "
- "[no_waitq=0|1]\n"
- " [ofreg=OFREG] [sync=0|1] [thr=THR] "
- "[time=0|1|2[,TO]]\n"
- " [verbose=VERB] [--dry-run] [--pre-fetch] "
- "[--verbose]\n"
- " [--version]\n\n"
+ " [ese=0|1] [fua=0|1|2|3] [hipri=NRQS] "
+ "[mrq=NRQS]\n"
+ " [no_waitq=0|1] [ofreg=OFREG] [sync=0|1] "
+ "[thr=THR]\n"
+ " [time=0|1|2[,TO]] [verbose=VERB] [--dry-run] "
+ "[--pre-fetch]\n"
+ " [--verbose] [--version]\n\n"
" where: operands have the form name=value and are pecular to "
"'dd'\n"
" style commands, and options start with one or "
@@ -901,12 +914,13 @@ page2:
"kibibytes;\n"
" must be power of two, >= page_size "
"(typically 4)\n"
+ " ese=0|1 exit on secondary error when 1, else continue\n"
" fua force unit access: 0->don't(def), 1->OFILE, "
"2->IFILE,\n"
" 3->OFILE+IFILE\n"
" ibs IFILE logical block size, cannot differ from "
"obs or bs\n"
- " hipri similar to mrq=NRQS operand but does set mrq "
+ " hipri similar to mrq=NRQS operand but also sets "
"hipri flag\n"
" mrq NRQS is number of cmds placed in each sg "
"ioctl\n"
@@ -939,7 +953,7 @@ page3:
" where: 'iflag=<arg>' and 'oflag=<arg>' arguments are listed "
"below:\n\n"
" 00 use all zeros instead of if=IFILE (only in "
- "iflags)\n"
+ "iflag)\n"
" append append output to OFILE (assumes OFILE is "
"regular file)\n"
" coe continue of error (reading, fills with zeros)\n"
@@ -950,7 +964,7 @@ page3:
" dsync sets the O_SYNC flag on open()\n"
" excl sets the O_EXCL flag on open()\n"
" ff use all 0xff bytes instead of if=IFILE (only in "
- "iflags)\n"
+ "iflag)\n"
" fua sets the FUA (force unit access) in SCSI READs "
"and WRITEs\n"
" hipri set HIPRI flag and use blk_poll() for "
@@ -966,7 +980,7 @@ page3:
" qtail queue new request at tail of block queue (def: "
"q at head)\n"
" random use random data instead of if=IFILE (only in "
- "iflags)\n"
+ "iflag)\n"
" serial serialize sg command execution (def: overlap)\n"
" wq_excl set SG_CTL_FLAGM_EXCL_WAITQ on this sg fd\n"
"\n"
@@ -1149,6 +1163,9 @@ sig_listen_thread(struct global_collection * clp)
pr2serr_lk("%s: stall at pack_id=%d "
"detected\n", __func__, pack_id);
}
+ pr2serr_lk("%s: stall at pack_id=%d, dump sg/debug\n",
+ __func__, pack_id);
+ system_wrapper("/usr/bin/cat /proc/scsi/sg/debug\n");
}
} else {
stall_count = 0;
@@ -1389,7 +1406,7 @@ read_write_thread(struct global_collection * clp, int id, bool singleton)
clp->infant_cv.notify_one();
singleton = false;
}
- if (rep->stop_after_write) {
+ if (rep->stop_after_write || rep->stop_now) {
shutting_down = true;
break;
}
@@ -1938,6 +1955,7 @@ mrq0_again:
}
if (t_v4p->device_status || t_v4p->transport_status ||
t_v4p->driver_status) {
+ rep->stop_now = true;
pr2serr_lk("[%d] t_v4[%d]:\n", id, k);
lk_chk_n_print4(" ", t_v4p, vb > 4);
return q_blks;
@@ -2138,6 +2156,15 @@ try_again:
"out_q/fin blks=%u/%u\n", __func__, o_seg_blks, num_good,
in_mrq_q_blks, in_fin_blks, out_mrq_q_blks, out_fin_blks);
+ if (clp->ese) {
+ int sres = ctl_v4.spare_out;
+
+ if (sres != 0) {
+ clp->reason_res.store(sg_convert_errno(sres));
+ pr2serr_lk("Exit due to secondary error [%d]\n", sres);
+ return -sres;
+ }
+ }
if (num_good < 0)
return -ENODATA;
else {
@@ -2377,12 +2404,14 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
uint32_t in_fin_blks = 0;
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;
struct sg_io_v4 * t_v4p = &t_v4;
struct flags_t * iflagsp = &clp->in_flags;
struct flags_t * oflagsp = &clp->out_flags;
- int vb = clp->verbose;
+ const char * const a_ioctl_s = "do_both_sg_segment_mrq0: after "
+ "ioctl(SG_IO)";
id = rep->id;
pack_id_base = id * PACK_ID_TID_MULTIPLIER;
@@ -2455,8 +2484,7 @@ mrq0_again:
res = ioctl(rep->infd, SG_IO, t_v4p);
err = errno;
if (vb > 5)
- v4hdr_out_lk("do_both_sg_segment_mrq0: >> after ioctl(SG_IO)",
- t_v4p, id, false);
+ v4hdr_out_lk(a_ioctl_s, t_v4p, id, false);
if (res < 0) {
if (E2BIG == err)
sg_take_snap(rep->infd, id, true);
@@ -2471,6 +2499,7 @@ mrq0_again:
}
if (t_v4p->device_status || t_v4p->transport_status ||
t_v4p->driver_status) {
+ rep->stop_now = true;
pr2serr_lk("[%d] t_v4[%d]:\n", id, k);
lk_chk_n_print4(" ", t_v4p, vb > 4);
return min<int>(in_fin_blks, out_fin_blks);
@@ -2506,8 +2535,7 @@ mrq0_again2:
res = ioctl(rep->outfd, SG_IO, t_v4p);
err = errno;
if (vb > 5)
- v4hdr_out_lk("do_both_sg_segment_mrq0: >> after ioctl(SG_IO)",
- t_v4p, id, false);
+ v4hdr_out_lk(a_ioctl_s, t_v4p, id, false);
if (res < 0) {
if (E2BIG == err)
sg_take_snap(rep->outfd, id, true);
@@ -2522,6 +2550,7 @@ mrq0_again2:
}
if (t_v4p->device_status || t_v4p->transport_status ||
t_v4p->driver_status) {
+ rep->stop_now = true;
pr2serr_lk("[%d] t_v4[%d]:\n", id, k);
lk_chk_n_print4(" ", t_v4p, vb > 4);
return min<int>(in_fin_blks, out_fin_blks);
@@ -2763,6 +2792,15 @@ try_again:
"out_q/fin blks=%u/%u\n", __func__, o_seg_blks, num_good,
in_mrq_q_blks, in_fin_blks, out_mrq_q_blks, out_fin_blks);
+ if (clp->ese) {
+ int sres = ctl_v4.spare_out;
+
+ if (sres != 0) {
+ clp->reason_res.store(sg_convert_errno(sres));
+ pr2serr_lk("Exit due to secondary error [%d]\n", sres);
+ return -sres;
+ }
+ }
if (num_good < 0)
res = -ENODATA;
else {
@@ -3303,6 +3341,13 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp,
goto syn_err;
}
clp->elem_sz = n * 1024;
+ } else if (0 == strcmp(key, "ese")) {
+ n = sg_get_num(buf);
+ if (n < 0) {
+ pr2serr("ese= wants 0 (default) or 1\n");
+ goto syn_err;
+ }
+ clp->ese = !!n;
} else if (0 == strcmp(key, "fua")) {
n = sg_get_num(buf);
if (n & 1)
@@ -3979,8 +4024,10 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
- if ((FT_SG == clp->in_type ) && (FT_SG == clp->out_type)) {
- ;
+ if ((FT_SG == clp->in_type) && (FT_SG == clp->out_type)) {
+ if (clp->in_flags.serial || clp->out_flags.serial)
+ pr2serr("serial flag ignored when both IFILE and OFILE are sg "
+ "devices\n");
} else if (clp->in_flags.order)
pr2serr("Warning: oflag=order only active on sg->sg copies\n");
@@ -4140,7 +4187,6 @@ fini:
if ((clp->outregfd >= 0) && (STDOUT_FILENO != clp->outregfd) &&
(FT_DEV_NULL != clp->outreg_type))
close(clp->outregfd);
- res = exit_status;
print_stats("");
if (clp->dio_incomplete_count.load()) {
int fd;
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 7c0c9ed6..a678cad5 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -36,7 +36,7 @@
* renamed [20181221]
*/
-static const char * version_str = "1.99 20210216";
+static const char * version_str = "2.00 20210305";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -931,12 +931,13 @@ usage(int pg_num)
" null,sync]\n"
" count number of blocks to copy (def: device size)\n"
" if file or device to read from (def: stdin)\n"
- " iflag comma separated list from: [coe,defres,dio,"
+ " iflag comma separated list from: [00,coe,defres,dio,"
"direct,dpo,\n"
- " dsync,excl,fua,masync,mmap,mrq_immed,mrq_svb,"
- "nodur,\n"
- " no_waitq,noxfer,null,qtail,same_fds,"
- "v3,v4,wq_excl]\n"
+ " dsync,excl,ff,fua,hipri,masync,mmap,mrq_immed,"
+ "mrq_svb,\n"
+ " nocreat,nodur,no_waitq,noxfer,null,qhead,qtail,"
+ "random,\n"
+ " 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=.' "
@@ -1051,6 +1052,7 @@ page3:
" no_waitq when non-blocking (async) don't use wait "
"queue\n"
" noxfer no transfer to/from the user space\n"
+ " null does nothing, placeholder\n"
" qhead queue new request at head of block queue\n"
" qtail queue new request at tail of block queue (def: "
"q at head)\n"