aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2021-01-31 23:48:11 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2021-01-31 23:48:11 +0000
commit245e8d347a48c70d5a2e047bf85b98609b64b900 (patch)
tree83cfbd55ba4bbfe0169baa641627e7c699dd1c2a
parent070eae9c6711b900abc1a46e09de0bbc515028a2 (diff)
downloadsg3_utils-245e8d347a48c70d5a2e047bf85b98609b64b900.tar.gz
sg_zone: add Remove element and modify zones command; testing/sg_mrq_dd work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@874 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--COVERAGE3
-rw-r--r--ChangeLog3
-rw-r--r--doc/sg_zone.836
-rw-r--r--src/sg_zone.c76
-rw-r--r--testing/sg_mrq_dd.cpp97
-rw-r--r--testing/uapi_sg.h6
6 files changed, 164 insertions, 57 deletions
diff --git a/COVERAGE b/COVERAGE
index f59f047e..9a3df8b0 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -71,6 +71,7 @@ RECEIVE COPY OPERATING PARAMETERS ddpt, sg_copy_results, sg_xcopy, ++
RECEIVE COPY STATUS(LID1) sg_copy_results, ++
RECEIVE DIAGNOSTIC RESULTS sg_senddiag, sg_ses, sg_ses_microcode ++
RECEIVE ROD TOKEN INFORMATION ddpt, ddptctl ++
+REMOVE ELEMENT AND MODIFY ZONES sg_zone
REPORT ALL ROD TOKENS ddptctl ++
REPORT IDENTIFYING INFORMATION sg_ident, ++ (2)
REPORT LUNS sg_luns, ++
@@ -177,4 +178,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-23rd April 2020
+23rd January 2021
diff --git a/ChangeLog b/ChangeLog
index e10ff8ff..3199fc60 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 pre-release sg3_utils-1.46 [20210113] [svn: r873]
+Changelog for pre-release sg3_utils-1.46 [20210131] [svn: r874]
- sg_rep_pip: report new provisioning initialization pattern cmd
- sg_turs: estimated time-to-ready [20-061r2]
- add --delay=MS option
@@ -23,6 +23,7 @@ Changelog for pre-release sg3_utils-1.46 [20210113] [svn: r873]
- sg_modes: document '-s' option (same as '-6')
- sg_sanitize + sg_format: when --verbose given once report
probable success; without --verbose 'no news is good news'
+ - sg_zone: add Remove element and modify zones command
- sg_raw: increase maximum data-in and data-out buffer size
from 64 KB to 1 MB
- fix --cmdfile= handling
diff --git a/doc/sg_zone.8 b/doc/sg_zone.8
index e3dfd3c7..a2aa45fc 100644
--- a/doc/sg_zone.8
+++ b/doc/sg_zone.8
@@ -1,21 +1,23 @@
-.TH SG_ZONE "8" "May 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_ZONE "8" "January 2021" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
-sg_zone \- send SCSI OPEN, CLOSE, FINISH or SEQUENTIALIZE ZONE command
+sg_zone \- send a SCSI ZONE modifying command
.SH SYNOPSIS
.B sg_zone
-[\fI\-\-all\fR] [\fI\-\-close\fR] [\fI\-\-count=ZC\fR] [\fI\-\-finish\fR]
-[\fI\-\-help\fR] [\fI\-\-open\fR] [\fI\-\-sequentialize\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-zone=ID\fR] \fIDEVICE\fR
+[\fI\-\-all\fR] [\fI\-\-close\fR] [\fI\-\-count=ZC\fR] [\fI\-\-element=EID\fR]
+[\fI\-\-finish\fR] [\fI\-\-help\fR] [\fI\-\-open\fR] [\fI\-\-remove\fR]
+[\fI\-\-sequentialize\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+[\fI\-\-zone=ID\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
-Sends a SCSI OPEN ZONE, CLOSE ZONE, FINISH ZONE or SEQUENTIALIZE ZONE
-command to the \fIDEVICE\fR. All but the last are found in the soon to
-be released ZBC standard (close to draft ZBC BSR INCITS 536 revision 05).
-The SEQUENTIALIZE ZONE command was added in zbc2r01b.
+Sends a SCSI OPEN ZONE, CLOSE ZONE, FINISH ZONE, REMOVE ELEMENT AND MODIFY
+ZONES or SEQUENTIALIZE ZONE command to the \fIDEVICE\fR. All but the last
+two are found in the ZBC standard (INCITS 536-2016). The REMOVE ELEMENT AND
+MODIFY ZONES command was added in zbc2r07 while the SEQUENTIALIZE ZONE command
+was added in zbc2r01b.
.PP
-One and only one of the \fI\-\-open\fR, \fI\-\-close\fR, \fI\-\-finish\fR
-and \fI\-\-sequentialize\fR options can be chosen.
+One and only one of the \fI\-\-open\fR, \fI\-\-close\fR, \fI\-\-finish\fR,
+\fI\-\-remove\fR and \fI\-\-sequentialize\fR options can be chosen.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
@@ -30,6 +32,12 @@ ZC is placed in the Zone Count field in the cdb of all four commands
supported by this utility. ZC should be a value from 0 to 65535 (0xffff)
inclusive.
.TP
+\fB\-e\fR, \fB\-\-element\fR=\fIEID\fR
+where \fIEID\fR is an element identifier which is a 32 bit unsigned integer
+starting at one. This field is used by the REMOVE ELEMENT AND MODIFY ZONES
+command and its default value is zero (which is invalid). So the user needs
+to supply a valid element identifier when \fI\-\-remove\fR is used.
+.TP
\fB\-f\fR, \fB\-\-finish\fR
causes the FINISH ZONE command to be sent to the \fIDEVICE\fR.
.TP
@@ -39,6 +47,10 @@ output the usage message then exit.
\fB\-o\fR, \fB\-\-open\fR
causes the OPEN ZONE command to be sent to the \fIDEVICE\fR.
.TP
+\fB\-r\fR, \fB\-\-remove\fR
+causes the REMOVE ELEMENT AND MODIFY ZONES command to be sent to the
+\fIDEVICE\fR. In practice, \fI\-\-element=EID\fR needs to be also given.
+.TP
\fB\-S\fR, \fB\-\-sequentialize\fR
causes the SEQUENTIALIZE ZONE command to be sent to the \fIDEVICE\fR.
.TP
@@ -61,7 +73,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2014\-2018 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/src/sg_zone.c b/src/sg_zone.c
index 14fa0885..18a07958 100644
--- a/src/sg_zone.c
+++ b/src/sg_zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019 Douglas Gilbert.
+ * Copyright (c) 2014-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.
@@ -37,13 +37,14 @@
* to the given SCSI device. Based on zbc-r04c.pdf .
*/
-static const char * version_str = "1.14 20191220";
+static const char * version_str = "1.15 20210122";
#define SG_ZONING_OUT_CMDLEN 16
#define CLOSE_ZONE_SA 0x1
#define FINISH_ZONE_SA 0x2
#define OPEN_ZONE_SA 0x3
#define SEQUENTIALIZE_ZONE_SA 0x10
+#define REM_ELEM_MOD_ZONES_SA 0x1a /* uses SERVICE ACTION IN(16) */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
#define DEF_PT_TIMEOUT 60 /* 60 seconds */
@@ -53,10 +54,12 @@ static struct option long_options[] = {
{"all", no_argument, 0, 'a'},
{"close", no_argument, 0, 'c'},
{"count", required_argument, 0, 'C'},
+ {"element", required_argument, 0, 'e'},
{"finish", no_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"open", no_argument, 0, 'o'},
- {"reset-all", no_argument, 0, 'R'},
+ {"remove", no_argument, 0, 'r'},
+ {"reset-all", no_argument, 0, 'R'}, /* same as --all */
{"reset_all", no_argument, 0, 'R'},
{"sequentialize", no_argument, 0, 'S'},
{"verbose", no_argument, 0, 'v'},
@@ -67,17 +70,21 @@ static struct option long_options[] = {
/* Indexed by service action */
static const char * sa_name_arr[] = {
- "no SA=0",
+ "no SA=0", /* 0x0 */
"Close zone",
"Finish zone",
"Open zone",
"-", "-", "-", "-",
- "-", /* 0x8 */
+ "Zone activate", /* 0x8 */
"-", "-", "-", "-",
"-",
"-",
"-",
"Sequentialize zone", /* 0x10 */
+ "-", "-", "-", "-",
+ "-", "-", "-", "-",
+ "-",
+ "Remove element and modify zones", /* 0x1a */
};
@@ -85,17 +92,25 @@ static void
usage()
{
pr2serr("Usage: "
- "sg_zone [--all] [--close] [--count=ZC] [--finish] [--help]\n"
- " [--open] [--sequentialize] [--verbose] "
- "[--version]\n"
- " [--zone=ID] DEVICE\n");
+ "sg_zone [--all] [--close] [--count=ZC] [--element=EID] "
+ "[--finish]\n"
+ " [--help] [--open] [--remove] "
+ "[--sequentialize] "
+ "[--verbose]\n"
+ " [--version] [--zone=ID] DEVICE\n");
pr2serr(" where:\n"
" --all|-a sets the ALL flag in the cdb\n"
" --close|-c issue CLOSE ZONE command\n"
" --count=ZC|-C ZC set zone count field (def: 0)\n"
+ " --element=EID|-e EID EID is the element identifier to "
+ "remove;\n"
+ " default is 0 which is an invalid "
+ "EID\n"
" --finish|-f issue FINISH ZONE command\n"
" --help|-h print out usage message\n"
" --open|-o issue OPEN ZONE command\n"
+ " --remove|-r issue REMOVE ELEMENT AND MODIFY ZONES "
+ "command\n"
" --sequentialize|-S issue SEQUENTIALIZE ZONE command\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n"
@@ -104,8 +119,8 @@ usage()
"Performs a SCSI OPEN ZONE, CLOSE ZONE, FINISH ZONE or "
"SEQUENTIALIZE\nZONE command. ID is decimal by default, for hex "
"use a leading '0x'\nor a trailing 'h'. Either --close, "
- "--finish, --open or\n--sequentialize option needs to be "
- "given.\n");
+ "--finish, --open, --remove or\n--sequentialize option needs to "
+ "be given.\n");
}
/* Invokes the zone out command indicated by 'sa' (ZBC). Return of 0
@@ -122,10 +137,15 @@ sg_ll_zone_out(int sg_fd, int sa, uint64_t zid, uint16_t zc, bool all,
char b[64];
zo_cdb[1] = 0x1f & sa;
- sg_put_unaligned_be64(zid, zo_cdb + 2);
- sg_put_unaligned_be16(zc, zo_cdb + 12);
- if (all)
- zo_cdb[14] = 0x1;
+ if (REM_ELEM_MOD_ZONES_SA == sa) { /* zid carries element identifier */
+ zo_cdb[0] = SG_SERVICE_ACTION_IN_16; /* N.B. changing opcode */
+ sg_put_unaligned_be32((uint32_t)zid, zo_cdb + 10);
+ } else {
+ sg_put_unaligned_be64(zid, zo_cdb + 2);
+ sg_put_unaligned_be16(zc, zo_cdb + 12);
+ if (all)
+ zo_cdb[14] = 0x1;
+ }
sg_get_opcode_sa_name(zo_cdb[0], sa, -1, sizeof(b), b);
if (verbose) {
char d[128];
@@ -143,7 +163,7 @@ sg_ll_zone_out(int sg_fd, int sa, uint64_t zid, uint16_t zc, bool all,
set_scsi_pt_cdb(ptvp, zo_cdb, sizeof(zo_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, "reset write pointer", res, noisy,
+ ret = sg_cmds_process_resp(ptvp, b, res, noisy,
verbose, &sense_cat);
if (-1 == ret)
ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
@@ -171,6 +191,7 @@ main(int argc, char * argv[])
bool close = false;
bool finish = false;
bool open = false;
+ bool reamz = false;
bool sequentialize = false;
bool verbose_given = false;
bool version_given = false;
@@ -188,7 +209,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "acC:fhoRSvVz:", long_options,
+ c = getopt_long(argc, argv, "acC:e:fhorRSvVz:", long_options,
&option_index);
if (c == -1)
break;
@@ -211,6 +232,16 @@ main(int argc, char * argv[])
}
zc = (uint16_t)n;
break;
+ case 'e':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--element=EID'\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (0 == ll)
+ pr2serr("Warning: 0 is an invalid element identifier\n");
+ zid = (uint64_t)ll;
+ break;
case 'f':
finish = true;
sa = FINISH_ZONE_SA;
@@ -223,6 +254,10 @@ main(int argc, char * argv[])
open = true;
sa = OPEN_ZONE_SA;
break;
+ case 'r':
+ reamz = true;
+ sa = REM_ELEM_MOD_ZONES_SA;
+ break;
case 'S':
sequentialize = true;
sa = SEQUENTIALIZE_ZONE_SA;
@@ -283,9 +318,10 @@ main(int argc, char * argv[])
return 0;
}
- if (1 != ((int)close + (int)finish + (int)open + (int)sequentialize)) {
- pr2serr("one from the --close, --finish, --open and --sequentialize "
- "options must be given\n");
+ if (1 != ((int)close + (int)finish + (int)open + (int)sequentialize +
+ (int)reamz)) {
+ pr2serr("one of these options: --close, --finish, --open "
+ "--sequentialize and\n--remove must be given\n");
usage();
return SG_LIB_CONTRADICT;
}
diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp
index 8496617e..32f0f4d6 100644
--- a/testing/sg_mrq_dd.cpp
+++ b/testing/sg_mrq_dd.cpp
@@ -30,7 +30,7 @@
*
*/
-static const char * version_str = "1.17 20210106";
+static const char * version_str = "1.18 20210130";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -144,6 +144,7 @@ using namespace std;
#define DEF_NUM_THREADS 4
#define MAX_NUM_THREADS 1024 /* was SG_MAX_QUEUE with v3 driver */
#define DEF_MRQ_NUM 16
+#define DEF_STALL_THRESH 4
#ifndef RAW_MAJOR
#define RAW_MAJOR 255 /*unlikely value */
@@ -243,6 +244,7 @@ struct global_collection /* one instance visible to all threads */
atomic<int> dio_incomplete_count;
atomic<int> sum_of_resids;
atomic<int> reason_res;
+ atomic<int> most_recent_pack_id;
int verbose;
int dry_run;
bool mrq_eq_0; /* true when user gives mrq=0 */
@@ -340,9 +342,9 @@ static sigset_t signal_set;
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
static int sg_in_open(struct global_collection *clp, const char *inf,
- uint8_t **mmpp, int *mmap_len);
+ uint8_t **mmpp, int *mmap_len, bool move_data);
static int sg_out_open(struct global_collection *clp, const char *outf,
- uint8_t **mmpp, int *mmap_len);
+ uint8_t **mmpp, int *mmap_len, bool move_data);
static int do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
scat_gath_iter & o_sg_it, int seg_blks,
vector<cdb_arr_t> & a_cdb,
@@ -1101,20 +1103,57 @@ read_blkdev_capacity(int sg_fd, int64_t * num_sect, int * sect_sz)
#endif
}
+/* Has an infinite loop doing a timed wait for any signals in sig_set. After
+ * each timeout (300 ms) checks if the most_recent_pack_id atomic integer
+ * has changed. If not after another two timeouts announces a stall has
+ * been detected. If shutting down atomic is true breaks out of loop and
+ * shuts down this thread. Other than that, this thread is normally cancelled
+ * by the main thread, after other threads have exited. */
static void
sig_listen_thread(struct global_collection * clp)
{
- int sig_number;
-
+ bool stall_reported = false;
+ int stall_count = 0;
+ int prev_pack_id = 0;
+ int sig_number, pack_id;
+ struct timespec ts;
+ struct timespec * tsp = &ts;
+
+ tsp->tv_sec = 0;
+ tsp->tv_nsec = 300 * 1000 * 1000; /* 300 ms */
while (1) {
- sigwait(&signal_set, &sig_number);
+ sig_number = sigtimedwait(&signal_set, NULL, tsp);
if (shutting_down)
break;
+ if (sig_number < 0) {
+ int err = errno;
+
+ if (EAGAIN == err) { /* timeout */
+ pack_id = clp->most_recent_pack_id.load();
+ if (pack_id == prev_pack_id) {
+ ++stall_count;
+ if (0 == (stall_count % DEF_STALL_THRESH)) {
+ if (! stall_reported) {
+ stall_reported = true;
+ pr2serr_lk("%s: stall at pack_id=%d "
+ "detected\n", __func__, pack_id);
+ }
+ }
+ } else {
+ stall_count = 0;
+ prev_pack_id = pack_id;
+ }
+ } else
+ pr2serr_lk("%s: sigtimedwait() errno=%d\n", __func__, err);
+ }
if (SIGINT == sig_number) {
pr2serr_lk("%sinterrupted by SIGINT\n", my_name);
clp->next_count_pos.store(-1);
+ shutting_down.store(true);
}
}
+ if (clp->verbose > 1)
+ pr2serr_lk("%s: exiting\n", __func__);
}
static bool
@@ -1236,7 +1275,7 @@ read_write_thread(struct global_collection * clp, int id, bool singleton)
if (in_is_sg && clp->infp) {
fd = sg_in_open(clp, clp->infp, (in_mmap ? &rep->buffp : NULL),
- (in_mmap ? &rep->mmap_len : NULL));
+ (in_mmap ? &rep->mmap_len : NULL), true);
if (fd < 0)
goto fini;
rep->infd = fd;
@@ -1250,7 +1289,7 @@ read_write_thread(struct global_collection * clp, int id, bool singleton)
}
if (out_is_sg && clp->outfp) {
fd = sg_out_open(clp, clp->outfp, (out_mmap ? &rep->buffp : NULL),
- (out_mmap ? &rep->mmap_len : NULL));
+ (out_mmap ? &rep->mmap_len : NULL), true);
if (fd < 0)
goto fini;
rep->outfd = fd;
@@ -1867,6 +1906,7 @@ sg_half_segment_mrq0(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
}
t_v4p->timeout = DEF_TIMEOUT;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
mrq0_again:
res = ioctl(fd, SG_IO, t_v4p);
err = errno;
@@ -1984,6 +2024,7 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
t_v4p->timeout = DEF_TIMEOUT;
mrq_q_blks += num;
t_v4p->request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
a_v4.push_back(t_v4);
sg_it.add_blks(num);
@@ -2015,8 +2056,10 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
ctl_v4.dout_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
ctl_v4.din_xferp = (uint64_t)a_v4.data(); /* response array */
ctl_v4.din_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
- if (false /* allow_mrq_abort */)
+ if (false /* allow_mrq_abort */) {
ctl_v4.request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(ctl_v4.request_extra);
+ }
if (vb && vb_first_time.load()) {
pr2serr_lk("First controlling object output by ioctl(%s), flags: "
@@ -2393,6 +2436,7 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->din_xfer_len = num * clp->bs;
t_v4p->timeout = DEF_TIMEOUT;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
mrq0_again:
res = ioctl(rep->infd, SG_IO, t_v4p);
err = errno;
@@ -2442,6 +2486,7 @@ mrq0_again:
t_v4p->dout_xfer_len = num * clp->bs;
t_v4p->timeout = DEF_TIMEOUT;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
mrq0_again2:
res = ioctl(rep->outfd, SG_IO, t_v4p);
err = errno;
@@ -2574,6 +2619,7 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->timeout = DEF_TIMEOUT;
in_mrq_q_blks += num;
t_v4p->request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
a_v4.push_back(t_v4);
/* Now build the command/request for write-side (WRITE or VERIFY) */
@@ -2597,6 +2643,7 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->timeout = DEF_TIMEOUT;
out_mrq_q_blks += num;
t_v4p->request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(t_v4p->request_extra);
a_v4.push_back(t_v4);
i_sg_it.add_blks(num);
@@ -2636,8 +2683,10 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
ctl_v4.dout_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
ctl_v4.din_xferp = (uint64_t)a_v4.data(); /* response array */
ctl_v4.din_xfer_len = a_v4.size() * sizeof(struct sg_io_v4);
- if (false /* allow_mrq_abort */)
+ if (false /* allow_mrq_abort */) {
ctl_v4.request_extra = mrq_pack_id_base + ++rep->mrq_pack_id_off;
+ clp->most_recent_pack_id.store(ctl_v4.request_extra);
+ }
if (vb && vb_first_time.load()) {
pr2serr_lk("First controlling object output by ioctl(%s), flags: "
@@ -2721,6 +2770,7 @@ fini:
return res < 0 ? res : (min<int>(in_fin_blks, out_fin_blks));
}
+#if 0
/* Returns number found and (partially) processed. 'num' is the number of
* completions to wait for when > 0. When 'num' is zero check all inflight
* request on 'fd' and return quickly if none completed (i.e. don't wait)
@@ -2745,6 +2795,7 @@ sg_blk_poll(int fd, int num)
}
return (seip->num == -1) ? -9999 : seip->num;
}
+#endif
/* Returns reserved_buffer_size/mmap_size if success, else 0 for failure */
static int
@@ -3040,7 +3091,7 @@ process_flags(const char * arg, struct flags_t * fp)
static int
sg_in_open(struct global_collection *clp, const char *inf, uint8_t **mmpp,
- int * mmap_lenp)
+ int * mmap_lenp, bool move_data)
{
int fd, err, n;
int flags = O_RDWR;
@@ -3060,9 +3111,12 @@ sg_in_open(struct global_collection *clp, const char *inf, uint8_t **mmpp,
perror(ebuff);
return -sg_convert_errno(err);
}
- n = sg_prepare_resbuf(fd, clp, true, mmpp);
- if (n <= 0)
- return -SG_LIB_FILE_ERROR;
+ if (move_data) {
+ n = sg_prepare_resbuf(fd, clp, true, mmpp);
+ if (n <= 0)
+ return -SG_LIB_FILE_ERROR;
+ } else
+ n = 0;
if (mmap_lenp)
*mmap_lenp = n;
return fd;
@@ -3070,7 +3124,7 @@ sg_in_open(struct global_collection *clp, const char *inf, uint8_t **mmpp,
static int
sg_out_open(struct global_collection *clp, const char *outf, uint8_t **mmpp,
- int * mmap_lenp)
+ int * mmap_lenp, bool move_data)
{
int fd, err, n;
int flags = O_RDWR;
@@ -3090,9 +3144,12 @@ sg_out_open(struct global_collection *clp, const char *outf, uint8_t **mmpp,
perror(ebuff);
return -sg_convert_errno(err);
}
- n = sg_prepare_resbuf(fd, clp, false, mmpp);
- if (n <= 0)
- return -SG_LIB_FILE_ERROR;
+ if (move_data) {
+ n = sg_prepare_resbuf(fd, clp, false, mmpp);
+ if (n <= 0)
+ return -SG_LIB_FILE_ERROR;
+ } else
+ n = 0;
if (mmap_lenp)
*mmap_lenp = n;
return fd;
@@ -3802,7 +3859,7 @@ main(int argc, char * argv[])
pr2serr("%sunable to use scsi tape device %s\n", my_name, inf);
return SG_LIB_FILE_ERROR;
} else if (FT_SG == clp->in_type) {
- clp->infd = sg_in_open(clp, inf, NULL, NULL);
+ clp->infd = sg_in_open(clp, inf, NULL, NULL, false);
if (clp->infd < 0)
return -clp->infd;
} else {
@@ -3841,7 +3898,7 @@ main(int argc, char * argv[])
pr2serr("%sunable to use scsi tape device %s\n", my_name, outf);
return SG_LIB_FILE_ERROR;
} else if (FT_SG == clp->out_type) {
- clp->outfd = sg_out_open(clp, outf, NULL, NULL);
+ clp->outfd = sg_out_open(clp, outf, NULL, NULL, false);
if (clp->outfd < 0)
return -clp->outfd;
} else if (FT_DEV_NULL == clp->out_type)
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index 0cdbc249..3d7e9326 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -97,8 +97,8 @@ typedef struct sg_io_hdr {
/* SG_FLAG_UNUSED_LUN_INHIBIT is ignored in sg v4 driver */
#define SG_FLAG_UNUSED_LUN_INHIBIT 2 /* ignored, was LUN overwrite in cdb */
#define SG_FLAG_MMAP_IO 4 /* request memory mapped IO */
-/* no transfer of kernel buffers to/from user space; used for sharing */
-#define SG_FLAG_NO_DXFER 0x10000
+/* no transfers between kernel<-->user space; keep device<-->kernel xfers */
+#define SG_FLAG_NO_DXFER 0x10000 /* See comment on previous line! */
/* defaults: for sg driver (v3_v4): Q_AT_HEAD; for block layer: Q_AT_TAIL */
#define SG_FLAG_Q_AT_TAIL 0x10
#define SG_FLAG_Q_AT_HEAD 0x20
@@ -124,7 +124,7 @@ typedef struct sg_io_hdr {
#define SGV4_FLAG_DEV_SCOPE 0x2000 /* permit SG_IOABORT to have wider scope */
#define SGV4_FLAG_SHARE 0x4000 /* share IO buffer; needs SG_SEIM_SHARE_FD */
#define SGV4_FLAG_DO_ON_OTHER 0x8000 /* available on either of shared pair */
-#define SGV4_FLAG_NO_DXFER SG_FLAG_NO_DXFER /* needed for sharing */
+#define SGV4_FLAG_NO_DXFER SG_FLAG_NO_DXFER /* but keep dev<-->kernel xfr */
#define SGV4_FLAG_KEEP_SHARE 0x20000 /* ... buffer for another dout command */
#define SGV4_FLAG_MULTIPLE_REQS 0x40000 /* 1 or more sg_io_v4-s in data-in */
#define SGV4_FLAG_EVENTFD 0x80000 /* signal completion on ... */