aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-29 07:13:59 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-29 07:13:59 +0000
commitc3da9a6b41cbae7940180645721a35becdd5bc99 (patch)
tree6704c41130a47d9b3bd9df2920dab9626f8754c1
parent7dff7ae9433763457872082271aac0487e14d158 (diff)
downloadsg3_utils-c3da9a6b41cbae7940180645721a35becdd5bc99.tar.gz
scripts: update 54-before-scsi-sg3_id.rules; more testing tweaks
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@820 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--CREDITS6
-rw-r--r--ChangeLog6
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--scripts/59-fc-wwpn-id.rules6
-rw-r--r--sg3_utils.spec6
-rw-r--r--testing/sg_tst_async.cpp153
-rw-r--r--testing/sgh_dd.cpp6
-rw-r--r--testing/uapi_sg.h43
9 files changed, 140 insertions, 90 deletions
diff --git a/CREDITS b/CREDITS
index d67a9a34..be90a425 100644
--- a/CREDITS
+++ b/CREDITS
@@ -12,7 +12,7 @@ Bart Van Assche <bart dot vanassche at sandisk dot com>
to replace pthread_cancel with pthread_kill [20180102]
Bean Huo <beanhuo dot micron dot com>
- sg_write_buffer: patch to allow comma or period separated bytes
+ sg_write_buffer: patch to allow comma or period separated bytes
(in decimal or hex) to be decoded when given as standard input.
Brian Bunker <Brian dot Bunker at netapp dot com> contributed
@@ -107,6 +107,8 @@ Mark Knibbs <markk at clara dot co dot uk>
Martin Schwenke <martin at meltin dot net> added the raw switch "-r" to sg_inq
+Martin Wilck <mwilck at suse dot com> contributed script files [20190425]
+
Nate Dailey < Nate dot Dailey at stratus dot com > extended sg_map for sparse
disk node names (e.g. /dev/sdaaa) [20050511]
@@ -145,4 +147,4 @@ Trent Piepho <xyzzy at speakeasy dot org> print out some "sense key specific"
Douglas Gilbert
-12th November 2018
+29th April 2019
diff --git a/ChangeLog b/ChangeLog
index 21688d03..19ac84c1 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 sg3_utils-1.45 [20190419] [svn: r819]
+Changelog for sg3_utils-1.45 [20190429] [svn: r820]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (spc5r20)
@@ -24,7 +24,9 @@ Changelog for sg3_utils-1.45 [20190419] [svn: r819]
- sg_cmds_process_resp(): two arguments removed
- add ${PACKAGE_VERSION} to '.so' name
- sg_pt_freebsd: fixes for FreeBSD 12.0 release
- - scripts/scsi-sg3_id: update rules
+ - scripts: update 54-before-scsi-sg3_id.rules,
+ scsi-enable-target-scan.sh and
+ 59-fc-wwpn-id.rules
- linux: add nanosecond durations when
SG3_UTILS_LINUX_NANO environment variable given
- rescan-scsi-bus: widen LUN 0 only scanning
diff --git a/README b/README
index 99c02400..fcf86847 100644
--- a/README
+++ b/README
@@ -541,4 +541,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-10th April 2019
+29th April 2019
diff --git a/debian/changelog b/debian/changelog
index 8d8bb482..687ce0fb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.45-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Fri, 04 Jan 2018 11:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Mon, 29 Apr 2019 08:00:00 +0200
sg3-utils (1.44-0.1) unstable; urgency=low
diff --git a/scripts/59-fc-wwpn-id.rules b/scripts/59-fc-wwpn-id.rules
index 81a20ad2..5ad0a5c8 100644
--- a/scripts/59-fc-wwpn-id.rules
+++ b/scripts/59-fc-wwpn-id.rules
@@ -7,9 +7,9 @@ KERNEL!="sd*", GOTO="fc_wwpn_end"
ENV{DEVTYPE}=="disk", IMPORT{program}="fc_wwpn_id %p"
ENV{DEVTYPE}=="partition", IMPORT{parent}="FC_*"
-ENV{FC_TARGET_WWPN}!="$*"; GOTO="fc_wwpn_end"
-ENV{FC_INITIATOR_WWPN}!="$*"; GOTO="fc_wwpn_end"
-ENV{FC_TARGET_LUN}!="$*"; GOTO="fc_wwpn_end"
+ENV{FC_TARGET_WWPN}!="?*", GOTO="fc_wwpn_end"
+ENV{FC_INITIATOR_WWPN}!="?*", GOTO="fc_wwpn_end"
+ENV{FC_TARGET_LUN}!="?*", GOTO="fc_wwpn_end"
ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-path/fc-$env{FC_INITIATOR_WWPN}-$env{FC_TARGET_WWPN}-lun-$env{FC_TARGET_LUN}"
ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-path/fc-$env{FC_INITIATOR_WWPN}-$env{FC_TARGET_WWPN}-lun-$env{FC_TARGET_LUN}-part%n"
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 31e6c3ae..336edc5d 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -21,8 +21,8 @@ disks (sg_start); do self tests (sg_senddiag); and various other functions.
See the README, ChangeLog and COVERAGE files. Requires the linux kernel 2.4
series or later. In the 2.4 series SCSI generic device names (e.g. /dev/sg0)
must be used. In the 2.6 series and later other device names may be used as
-well (e.g. /dev/sda). Also some support for NVMe devices, esspecially with
-sg_ses to NVMe enclosures.
+well (e.g. /dev/sda). Also some support for NVMe devices, especially with
+sg_ses on NVMe enclosures.
Warning: Some of these tools access the internals of your system
and the incorrect usage of them may render your system inoperable.
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Fri Jan 04 2019 - dgilbert at interlog dot com
+* Mon Apr 29 2019 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.45
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp
index e33d8ec0..8638ceec 100644
--- a/testing/sg_tst_async.cpp
+++ b/testing/sg_tst_async.cpp
@@ -89,7 +89,7 @@
#include "sg_pt.h"
#include "sg_cmds.h"
-static const char * version_str = "1.28 20190414";
+static const char * version_str = "1.32 20190427";
static const char * util_name = "sg_tst_async";
/* This is a test program for checking the async usage of the Linux sg
@@ -134,6 +134,7 @@ using namespace std::chrono;
#define DEF_NUM_PER_THREAD 1000
#define DEF_NUM_THREADS 4
#define DEF_WAIT_MS 10 /* 0: yield or no wait */
+#define DEF_NANOSEC_WAIT 25000 /* 25 microsecs */
#define DEF_TIMEOUT_MS 20000 /* 20 seconds */
#define DEF_LB_SZ 512
#define DEF_BLOCKING 0
@@ -269,6 +270,7 @@ static struct option long_options[] = {
{"generic_sync", no_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{"lba", required_argument, 0, 'l'},
+ {"lbsz", required_argument, 0, 'L'},
{"maxqpt", required_argument, 0, 'M'},
{"mmap-io", no_argument, 0, 'm'},
{"mmap_io", no_argument, 0, 'm'},
@@ -299,17 +301,17 @@ static void
usage(void)
{
printf("Usage: %s [--cmd-time] [--direct] [--force] [--generic-sync]\n"
- " [--help] [--lba=LBA+] [--maxqpt=QPT] "
- "[--mmap-io]\n"
- " [--numpt=NPT] [--noxfer] [--override=OVN] "
- "[--pack-id]\n"
- " [--qat=AT] [-qfav=FAV] [--read] [--stats] "
- "[--submit]\n"
- " [--szlb=LB[,NLBS]] [--tnum=NT] [--tur] "
- "[--v3]\n"
- " [--v4] [--verbose] [--version] [--wait=MS] "
- "[--write]\n"
- " <sg_disk_device>*\n",
+ " [--help] [--lba=LBA+] [--lbsz=LBSZ] "
+ "[--maxqpt=QPT]\n"
+ " [--mmap-io] [--numpt=NPT] [--noxfer] "
+ "[--override=OVN]\n"
+ " [--pack-id] [--qat=AT] [-qfav=FAV] [--read] "
+ "[--stats]\n"
+ " [--submit] [--szlb=LB[,NLBS]] [--tnum=NT] "
+ "[--tur]\n"
+ " [--v3] [--v4] [--verbose] [--version] "
+ "[--wait=MS]\n"
+ " [--write] <sg_disk_device>*\n",
util_name);
printf(" where\n");
printf(" --cmd-time|-c calculate per command average time (ns)\n");
@@ -328,6 +330,9 @@ usage(void)
"(inclusive)\n"
" if hi_lba=-1 assume last block on "
"device\n");
+ printf(" --lbsz=LBSZ|-L LBSZ logical block size in bytes (def: "
+ "512)\n"
+ " should be power of 2 (0 --> 512)\n");
printf(" --maxqpt=QPT|-M QPT maximum commands queued per thread "
"(def:%d)\n", MAX_Q_PER_FD);
printf(" --mmap-io|-m mmap-ed IO (1 cmd outstanding per "
@@ -373,7 +378,7 @@ usage(void)
"by each READ and WRITE; zeros are written. If a\nlogical block "
"range is given, a uniform distribution generates a pseudo\n"
"random sequence of LBAs. Set environment variable\n"
- "SG3_UTILS_LINUX_NANO to get command timings in nanoseconds\n");
+ "SG3_UTILS_LINUX_NANO to get command timings in nanoseconds\n");
}
#ifdef __GNUC__
@@ -501,7 +506,7 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba,
ptp->flags = flags;
for (int k = 0;
- (submit ? ioctl(sg_fd, SG_IOSUBMIT, ptp) :
+ (submit ? ioctl(sg_fd, SG_IOSUBMIT_V3, ptp) :
write(sg_fd, ptp, sizeof(*ptp)) < 0);
++k) {
if ((ENOMEM == errno) && (k < MAX_CONSEC_NOMEMS)) {
@@ -527,9 +532,9 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba,
}
static int
-finish_sg3_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
- int & pack_id, bool receive, int wait_ms,
- unsigned int & eagains, unsigned int & nanosecs)
+finish_sg3_cmd(int sg_fd, command2execute cmd2exe, int & pack_id,
+ bool receive, int wait_ms, unsigned int & eagains,
+ unsigned int & nanosecs)
{
bool ok;
int res, k;
@@ -568,17 +573,15 @@ finish_sg3_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
ptp->pack_id = pack_id;
k = 0;
- while ((((res = receive ? ioctl(sg_fd, SG_IORECEIVE, ptp) :
+ while ((((res = receive ? ioctl(sg_fd, SG_IORECEIVE_V3, ptp) :
read(sg_fd, ptp, sizeof(*ptp)))) < 0) &&
(EAGAIN == errno)) {
++eagains;
- if (pack_id_force) {
- ++k;
- if (k > 10000) {
- pr2serr_lk("%s: unable to find pack_id=%d\n", __func__,
- pack_id);
- return -1; /* crash out */
- }
+ ++k;
+ if (k > 10000) {
+ pr2serr_lk("%s: sg_fd=%d: after %d EAGAINs, unable to find "
+ "pack_id=%d\n", __func__, sg_fd, k, pack_id);
+ return -1; /* crash out */
}
if (wait_ms > 0)
this_thread::sleep_for(milliseconds{wait_ms});
@@ -696,9 +699,9 @@ start_sg4_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba,
}
static int
-finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
- int & pack_id, bool receive, int wait_ms,
- unsigned int & eagains, unsigned int & nanosecs)
+finish_sg4_cmd(int sg_fd, command2execute cmd2exe, int & pack_id,
+ bool receive, int wait_ms, unsigned int & eagains,
+ unsigned int & nanosecs)
{
bool ok;
int res, k;
@@ -725,7 +728,7 @@ finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
np = "WRITE(16)";
break;
}
- ptp->guard = 'S';
+ ptp->guard = 'Q';
ptp->max_response_len = sizeof(sense_buffer);
ptp->response = (uint64_t)sense_buffer;
ptp->timeout = DEF_TIMEOUT_MS;
@@ -736,13 +739,11 @@ finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
while ((((res = ioctl(sg_fd, SG_IORECEIVE, ptp))) < 0) &&
(EAGAIN == errno)) {
++eagains;
- if (pack_id_force) {
- ++k;
- if (k > 10000) {
- pr2serr_lk("%s: unable to find pack_id=%d\n", __func__,
- pack_id);
- return -1; /* crash out */
- }
+ ++k;
+ if (k > 10000) {
+ pr2serr_lk("%s: sg_fd=%d: after %d EAGAINs, unable to find "
+ "pack_id=%d\n", __func__, sg_fd, k, pack_id);
+ return -1; /* crash out */
}
if (wait_ms > 0)
this_thread::sleep_for(milliseconds{wait_ms});
@@ -956,7 +957,10 @@ work_thread(int id, struct opts_t * op)
/* device name and hi_lba may depend on id */
n = op->dev_names.size();
dev_name = op->dev_names[id % n];
- blk_sz = op->blk_szs[id % n];
+ if (op->blk_szs.size() >= (unsigned)n)
+ blk_sz = op->blk_szs[id % n];
+ else
+ blk_sz = DEF_LB_SZ;
if ((UINT_MAX == op->hi_lba) && (n == (int)op->hi_lbas.size()))
hi_lba = op->hi_lbas[id % n];
else
@@ -1004,7 +1008,7 @@ work_thread(int id, struct opts_t * op)
seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS;
seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS;
seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_TIME_IN_NS;
- seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
+ seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
pr2serr_lk("ioctl(EXTENDED(TIME_IN_NS)) failed, errno=%d %s\n",
errno, strerror(errno));
@@ -1183,7 +1187,7 @@ work_thread(int id, struct opts_t * op)
if (is_rw) { /* get new lb buffer or one from free list */
if (free_lst.empty()) {
lbp = sg_memalign(op->lb_sz * op->num_lbs, 0, &free_lbp,
- vb > 6);
+ false);
if (NULL == lbp) {
err = "out of memory";
break;
@@ -1343,17 +1347,28 @@ work_thread(int id, struct opts_t * op)
}
}
n = (op->wait_ms > 0) ? op->wait_ms : 0;
- for (j = 0; (j < 1000000) && (0 == (res = poll(pfd, 1, n)));
- ++j)
- ;
+ if (n > 0) {
+ for (j = 0; (j < 1000000) &&
+ (0 == (res = poll(pfd, 1, n)));
+ ++j)
+ ;
+ if (j >= 1000000) {
+ err = "poll() looped 1 million times";
+ break;
+ }
+ if (res < 0) {
+ err = "poll(wait_ms) failed";
+ break;
+ }
+ } else {
+ struct timespec ts;
- if (j >= 1000000) {
- err = "poll() looped 1 million times";
- break;
- }
- if (res < 0) {
- err = "poll(wait_ms) failed";
- break;
+ ts.tv_sec = 0;
+ ts.tv_nsec = DEF_NANOSEC_WAIT;
+ if (nanosleep(&ts, NULL) < 0) {
+ err = "nanosleep() failed";
+ break;
+ }
}
}
} else { /* not full, not finished injecting */
@@ -1367,6 +1382,12 @@ work_thread(int id, struct opts_t * op)
num_to_read = num_waiting_read > 0 ?
num_waiting_read : 1;
} else {
+ num_waiting_read = 0;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING,
+ &num_waiting_read) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
if (num_waiting_read > (op->ovn / 2))
num_to_read = num_waiting_read / 2;
}
@@ -1401,12 +1422,12 @@ work_thread(int id, struct opts_t * op)
pack_id = -1;
ask = pack_id;
res = (op->v4) ?
- finish_sg4_cmd(sg_fd, op->c2e, op->pack_id_force, pack_id,
- op->submit, op->wait_ms,
- thr_fin_eagain_count, nanosecs) :
- finish_sg3_cmd(sg_fd, op->c2e, op->pack_id_force, pack_id,
- op->submit, op->wait_ms,
- thr_fin_eagain_count, nanosecs);
+ finish_sg4_cmd(sg_fd, op->c2e, pack_id, op->submit,
+ op->wait_ms, thr_fin_eagain_count,
+ nanosecs) :
+ finish_sg3_cmd(sg_fd, op->c2e, pack_id, op->submit,
+ op->wait_ms, thr_fin_eagain_count,
+ nanosecs);
if (res) {
err = "finish_sg3_cmd()";
if (ruip && (pack_id > 0)) {
@@ -1420,13 +1441,14 @@ work_thread(int id, struct opts_t * op)
}
break;
}
- if (vb > 4)
- pr2serr_lk("t_id=%d: finishing pack_id ask=%d, got=%d\n", id,
- ask, pack_id);
if (op->cmd_time && op->sg_vn_ge_30901)
sum_nanosecs += nanosecs;
++thr_async_finishes;
--num_outstanding;
+ if (vb > 4)
+ pr2serr_lk("t_id=%d: finishing pack_id ask=%d, got=%d, "
+ "outstanding=%d\n", id, ask, pack_id,
+ num_outstanding);
auto p = pi2buff.find(pack_id);
if (p == pi2buff.end()) {
@@ -1684,7 +1706,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "34cdfghl:mM:n:NO:pq:Q:Rs:St:TuvVw:W",
+ c = getopt_long(argc, argv, "34cdfghl:L:mM:n:NO:pq:Q:Rs:St:TuvVw:W",
long_options, &option_index);
if (c == -1)
break;
@@ -1693,10 +1715,14 @@ main(int argc, char * argv[])
case '3':
op->v3 = true;
op->v3_given = true;
+ op->v4 = false; /* if '-4 -3' take latter */
+ op->v4_given = false;
break;
case '4':
op->v4 = true;
op->v4_given = true;
+ op->v3 = false;
+ op->v3_given = false;
break;
case 'c':
op->cmd_time = true;
@@ -1741,6 +1767,15 @@ main(int argc, char * argv[])
return 1;
}
break;
+ case 'L':
+ op->lb_sz = sg_get_num(optarg);
+ if (op->lb_sz < 0) {
+ pr2serr_lk("--lbsz= expects power of 2\n");
+ return 1;
+ }
+ if (0 == op->lb_sz)
+ op->lb_sz = DEF_LB_SZ;
+ break;
case 'm':
op->mmap_io = true;
break;
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 4a8350a9..27438036 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.27 20190418";
+static const char * version_str = "1.28 20190419";
#ifdef __GNUC__
#ifndef __clang__
@@ -1028,7 +1028,7 @@ read_write_thread(void * v_tip)
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
- if (rep->debug > 1)
+ if (rep->debug > 2)
pr2serr_lk("thread=%d: tail-end my_index>=dd_count, "
"to_do=%u\n", rep->id,
(uint32_t)def_arr.first.size());
@@ -1142,7 +1142,7 @@ skip_force_out_sequence:
}
if (0 == rep->num_blks) {
if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
- if (rep->debug > 1)
+ if (rep->debug > 2)
pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id,
(uint32_t)def_arr.first.size());
sgh_do_def_mrq(rep, def_arr);
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index 053b0ffc..cea58f13 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -14,8 +14,8 @@
* Later extensions (versions 2, 3 and 4) to driver:
* Copyright (C) 1998 - 2018 Douglas Gilbert
*
- * Version 4.0.08 (20190419)
- * This version is for Linux 2.6, 3, 4 and 5 series kernels.
+ * Version 4.0.11 (20190427)
+ * This version is for Linux 4 and 5 series kernels.
*
* Documentation
* =============
@@ -144,7 +144,10 @@ typedef struct sg_scsi_id {
int scsi_type; /* TYPE_... defined in scsi/scsi.h */
short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
short d_queue_depth;/* device (or adapter) maximum queue length */
- __u8 scsi_lun[8]; /* full 8 byte SCSI LUN [new v4 driver] */
+ union {
+ int unused[2]; /* as per version 3 driver */
+ __u8 scsi_lun[8]; /* full 8 byte SCSI LUN [in v4 driver] */
+ };
} sg_scsi_id_t;
/* For backward compatibility v4 driver yields at most SG_MAX_QUEUE of these */
@@ -428,26 +431,34 @@ struct sg_header {
#define SG_NEXT_CMD_LEN 0x2283
/*
- * New ioctls to replace async write()/read() interface. Present in version
- * 4 and later of the sg driver [>20181014]. These two ioctls accept both
- * the sg_v3 interface (structure defined above) and the sg_v4 interface
- * (structure defined in <include/uapi/linux/bsg.h> ). Following "read" and
- * "write" terms are from the driver's POV, the _IO macros from users' POV.
+ * New ioctls to replace async (non-blocking) write()/read() interface.
+ * Present in version 4 and later of the sg driver [>20190427]. The
+ * SG_IOSUBMIT_V3 and SG_IORECEIVE_V3 ioctls accept the sg_v3 interface
+ * based on struct sg_io_hdr shown above. The SG_IOSUBMIT and SG_IORECEIVE
+ * ioctls accept the sg_v4 interface based on struct sg_io_v4 found in
+ * <include/uapi/linux/bsg.h>. These objects are passed by a pointer in
+ * the third argument of the ioctl.
*
- * SG_IOSUBMIT and SG_IORECEIVE can take a pointer to a v4 or v3 interface
- * which have different lengths (v4 is longer) but their definitions below
- * encode v4's length into the ioctl number. So users of the v3 interface
- * would be best to place a v3 structure inside (overwriting and at the start
- * of) a v4 structure and pass a pointer to that v4 structure to the ioctl.
+ * Data may be transferred both from the user space to the driver by these
+ * ioctls. Hence the _IOWR macro is used here to generate the ioctl number
+ * rather than _IOW or _IOR.
*/
-/* via pointer reads sg v3 or v4 object, optionally writes tag, so _IOWR */
+/* Submits a v4 interface object to driver, optionally receive tag back */
#define SG_IOSUBMIT _IOWR(SG_IOCTL_MAGIC_NUM, 0x41, struct sg_io_v4)
-/* via pointer optionally reads tag, writes sg v3 or v4 object, so _IOWR */
+
+/* Gives some v4 identifying info to driver, receives associated response */
#define SG_IORECEIVE _IOWR(SG_IOCTL_MAGIC_NUM, 0x42, struct sg_io_v4)
-/* via pointer reads v4 object (including tag), writes nothing, so _IOW */
+/* Provides identifying info about a prior submission (e.g. a tag) */
#define SG_IOABORT _IOW(SG_IOCTL_MAGIC_NUM, 0x43, struct sg_io_v4)
+/* Submits a v3 interface object to driver */
+#define SG_IOSUBMIT_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x45, struct sg_io_hdr)
+
+/* Gives some v3 identifying info to driver, receives associated response */
+#define SG_IORECEIVE_V3 _IOWR(SG_IOCTL_MAGIC_NUM, 0x46, struct sg_io_hdr)
+
+
/* command queuing is always on when the v3 or v4 interface is used */
#define SG_DEF_COMMAND_Q 0