aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg3_utils.84
-rw-r--r--doc/sg_raw.849
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/Makefile.in1
-rw-r--r--lib/sg_pt_freebsd.c178
-rw-r--r--lib/sg_pt_linux.c16
-rw-r--r--lib/sg_pt_linux_nvme.c24
-rw-r--r--lib/sg_pt_win32.c6
-rw-r--r--scripts/fc_wwpn_id6
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.in1
-rw-r--r--src/sg_raw.c103
-rw-r--r--src/sg_turs.c6
-rw-r--r--src/sgp_dd.c23
-rw-r--r--testing/uapi_sg.h12
18 files changed, 343 insertions, 100 deletions
diff --git a/ChangeLog b/ChangeLog
index 228e13df..2ffb0663 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,18 +2,18 @@ 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.46 [20201224] [svn: r871]
+Changelog for pre-release sg3_utils-1.46 [20210103] [svn: r872]
- sg_rep_pip: report new provisioning initialization pattern cmd
- sg_turs: estimated time-to-ready [20-061r2]
- add --delay=MS option
- sg_requests: substantial cleanup
- sg_vpd: add Format presets and Concurrent positioning ranges
- - add hot-pluggable field in standard Inquiry [20-0114r2]
+ - add hot-pluggable field in standard Inquiry [20-114r2]
- sg_inq: add hot-pluggable field in standard Inquiry
- sg_dd: --verify : separate category for miscompare errors
- --verify : oflag=coe continue on miscompares, counts them
- add oflag=nocreat and conv=nocreat : OFILE must exist
- - add iflag=00,ff, random flags
+ - add iflag=00, ff, random flags
- sg_get_elem_status: add ralwd bit sbc4r20a
- sg_write_x: add dld bits to write(32) [sbc4r19a]
- sg_rep_zones: print invalid write pointer LBA as -1 rather
@@ -27,6 +27,8 @@ Changelog for sg3_utils-1.46 [20201224] [svn: r871]
from 64 KB to 1 MB
- fix --cmdfile= handling
- add --nvm option to send commands from the NVM command set
+ - add --cmdset option to bypass cdb heuristic
+ - add --scan= first_opcode,last_opcode
- 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: restore elements and rebuild command added
diff --git a/debian/changelog b/debian/changelog
index b5ff68f2..895de16a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.46-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Sat, 05 Dec 2020 18:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Sun, 03 Jan 2021 21:00:00 -0500
sg3-utils (1.45-0.1) unstable; urgency=low
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index c4ab4569..467043b1 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "December 2020" "sg3_utils\-1.46" SG3_UTILS
+.TH SG3_UTILS "8" "January 2021" "sg3_utils\-1.46" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
@@ -759,7 +759,7 @@ CREDITS file and individual source files (in the 'src' directory).
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 1999\-2020 Douglas Gilbert
+Copyright \(co 1999\-2021 Douglas Gilbert
.br
Some utilities are distributed under a GPL version 2 license while
others, usually more recent ones, are under a FreeBSD license. The files
diff --git a/doc/sg_raw.8 b/doc/sg_raw.8
index bead0c4a..726283f8 100644
--- a/doc/sg_raw.8
+++ b/doc/sg_raw.8
@@ -1,13 +1,14 @@
-.TH SG_RAW "8" "August 2020" "sg3_utils\-1.46" SG3_UTILS
+.TH SG_RAW "8" "January 2021" "sg3_utils\-1.46" SG3_UTILS
.SH NAME
sg_raw \- send arbitrary SCSI or NVMe command to a device
.SH SYNOPSIS
.B sg_raw
-[\fI\-\-binary\fR] [\fI\-\-cmdfile=CF\fR] [\fI\-\-enumerate\fR]
-[\fI\-\-help\fR] [\fI\-\-infile=IFILE\fR] [\fI\-\-nosense\fR]
-[\fI\-\-nvm\fR] [\fI\-\-outfile=OFILE\fR] [\fI\-\-readonly\fR]
-[\fI\-\-request=RLEN\fR] [\fI\-\-send=SLEN\fR] [\fI\-\-skip=KLEN\fR]
-[\fI\-\-timeout=SECS\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+[\fI\-\-binary\fR] [\fI\-\-cmdfile=CF\fR] [\fI\-\-cmdset=CS\fR]
+[\fI\-\-enumerate\fR] [\fI\-\-help\fR] [\fI\-\-infile=IFILE\fR]
+[\fI\-\-nosense\fR] [\fI\-\-nvm\fR] [\fI\-\-outfile=OFILE\fR] [\fI\-\-raw\fR]
+[\fI\-\-readonly\fR] [\fI\-\-request=RLEN\fR] [\fI\-\-scan=FO,LO\fR]
+[\fI\-\-send=SLEN\fR] [\fI\-\-skip=KLEN\fR] [\fI\-\-timeout=SECS\fR]
+[\fI\-\-verbose\fR] [\fI\-\-version\fR]
\fIDEVICE\fR [CDB0 CDB1 ...]
.SH DESCRIPTION
This utility sends an arbitrary SCSI command (between 6 and 256 bytes) to
@@ -30,7 +31,9 @@ Experimental support has been added to send NVMe Admin and NVM commands to
the \fIDEVICE\fR. Since all NVMe commands are 64 bytes long it is more
convenient to use the \fI\-\-cmdfile=CF\fR option rather than type the 64
bytes of the NVMe command on the command line. See the section on NVME
-below.
+below. A heuristic based on command length is used to decide if the given
+command is SCSI or NVMe, to override this heuristic use the
+\fI\-\-cmdset=CS\fR option.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
The options are arranged in alphabetical order based on the long
@@ -44,6 +47,13 @@ Dump data in binary form, even when writing to stdout.
Without this option the command must be given on the command line, after
the options and the \fIDEVICE\fR.
.TP
+\fB\-C\fR, \fB\-\-cmdset\fR=\fICS\fR
+\fICS\fR is a number to indicate which command set (i.e. SCSI or NVMe)
+to use. 0, the default, causes a heuristic based on command length to be
+used. Use a \fICS\fR of 1 to override that heuristic and choose the SCSI
+command set. Use a \fICS\fR of 2 to override that heuristic and choose
+the NVMe command set.
+.TP
\fB\-h\fR, \fB\-\-help\fR
Display usage information and exit.
.TP
@@ -65,6 +75,10 @@ written in binary. By default, data is dumped in hex format to stdout.
If \fIOFILE\fR is '\-' then data is dumped in binary to stdout.
This option is ignored if \fI\-\-request\fR is not specified.
.TP
+\fB\-w\fR, \fB\-\-raw\fR
+interpret \fICF\fR (i.e. the command file) as containing binary. The default
+is to assume that it contains ASCII hexadecimal.
+.TP
\fB\-R\fR, \fB\-\-readonly\fR
Open \fIDEVICE\fR read\-only. The default (without this option) is to open
it read\-write.
@@ -85,6 +99,20 @@ the "allocation length" field in the cdb is large enough. In practice, the
\fIDEVICE\fR will return no more bytes than indicated in the "allocation
length" field of the cdb.
.TP
+\fB\-Q\fR, \fB\-\-scan\fR=\fIFO\fR,\fILO\fR
+Scan a range of opcodes (i.e. first byte of each command). The first opcode
+in the scan is \fIFO\fR (which is decimal unless it has a '0x' prefix or 'h'
+suffix). The last opcode in the scan is \fILO\fR. The maximum value of
+\fILO\fR is 255. The remaining bytes of the SCSI/NVMe command are as
+supplied at invocation.
+.br
+Warning: this option can be
+.B dangerous.
+Sending somewhat arbitrary commands to a device can have unexpected results.
+It is recommended that this option is used with the \fI\-\-cmdset=CS\fR
+option where \fICS\fR is 1 or 2 in order to stop the command set possibly
+changing during the scan.
+.TP
\fB\-s\fR, \fB\-\-send\fR=\fISLEN\fR
Read \fISLEN\fR bytes of data, either from stdin or from a file, and send
them to the \fIDEVICE\fR. In the SCSI transport, \fISLEN\fR becomes the
@@ -130,6 +158,11 @@ The CDB command name defined by T10 for the given CDB is shown if
the '\-vv' option is given. The command line syntax still needs to be
correct, so /dev/null may be used for the \fIDEVICE\fR since the CDB
command name decoding is done before the \fIDEVICE\fR is checked.
+.PP
+The intention of the \fI\-\-scan=FO,LO\fR option is to slightly simplify
+the process of finding hidden or undocumented commands. It should be used
+with care; for example checking for vendor specific SCSI
+commands: 'sg_raw \-\-cmdset=1 \-\-scan=0xc0,0xff /dev/sg1 0 0 0 0 0 0'.
.SH NVME SUPPORT
Support for NVMe (a.k.a. NVM Express) is currently experimental. NVMe concepts
map reasonably well to the SCSI architecture. A SCSI logical unit (LU) is
@@ -224,7 +257,7 @@ Written by Ingo van Lil
.SH "REPORTING BUGS"
Report bugs to <inguin at gmx dot de> or to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2001\-2020 Ingo van Lil
+Copyright \(co 2001\-2021 Ingo van Lil
.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/lib/Makefile.am b/lib/Makefile.am
index 7fa9dc73..aef8384f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -60,6 +60,7 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
+# AM_CFLAGS = -Wall -W -pedantic -std=c++20
lib_LTLIBRARIES = libsgutils2.la
diff --git a/lib/Makefile.in b/lib/Makefile.in
index a8bcf6ca..c20d06f4 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -375,6 +375,7 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
+# AM_CFLAGS = -Wall -W -pedantic -std=c++20
lib_LTLIBRARIES = libsgutils2.la
libsgutils2_la_LDFLAGS = -version-info 2:0:0 -no-undefined -release ${PACKAGE_VERSION}
libsgutils2_la_LIBADD = @GETOPT_O_FILES@
diff --git a/lib/sg_pt_freebsd.c b/lib/sg_pt_freebsd.c
index e98a2bb7..7c258f9e 100644
--- a/lib/sg_pt_freebsd.c
+++ b/lib/sg_pt_freebsd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2020 Douglas Gilbert.
+ * Copyright (c) 2005-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.
@@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-/* sg_pt_freebsd version 1.36 20200724 */
+/* sg_pt_freebsd version 1.37 20210102 */
#include <stdio.h>
#include <stdlib.h>
@@ -812,7 +812,8 @@ get_scsi_pt_resid(const struct sg_pt_base * vp)
{
const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
- return ((NULL == ptp) || (! ptp->nvme_our_sntl)) ? 0 : ptp->resid;
+ return ((NULL == ptp) || (ptp->is_nvme && ! ptp->nvme_our_sntl)) ?
+ 0 : ptp->resid;
}
void
@@ -866,16 +867,15 @@ get_scsi_pt_status_response(const struct sg_pt_base * vp)
const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp) {
- if (ptp->nvme_our_sntl)
- return ptp->scsi_status;
- else {
+ if (ptp->is_nvme && ! ptp->nvme_our_sntl) {
const struct freebsd_dev_channel *fdc_p;
fdc_p = get_fdc_cp(ptp);
if (NULL == fdc_p)
return -1;
return (int)fdc_p->nvme_status;
- }
+ } else
+ return ptp->scsi_status;
}
return -1;
}
@@ -887,16 +887,15 @@ get_pt_result(const struct sg_pt_base * vp)
const struct sg_pt_freebsd_scsi * ptp = &vp->impl;
if (ptp) {
- if (ptp->nvme_our_sntl)
- return (uint32_t)ptp->scsi_status;
- else {
+ if (ptp->is_nvme && ! ptp->nvme_our_sntl) {
const struct freebsd_dev_channel *fdc_p;
fdc_p = get_fdc_cp(ptp);
if (NULL == fdc_p)
return -1;
return fdc_p->nvme_result;
- }
+ } else
+ return (uint32_t)ptp->scsi_status;
}
return 0xffffffff;
}
@@ -920,7 +919,7 @@ get_scsi_pt_sense_buf(const struct sg_pt_base * vp)
return ptp->sense;
}
-/* Not impemented so return -1 . */
+/* Not implemented so return -1 . */
int
get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
{
@@ -1048,16 +1047,20 @@ get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
#define SCSI_INQUIRY_OPC 0x12
-#define SCSI_REPORT_LUNS_OPC 0xa0
-#define SCSI_TEST_UNIT_READY_OPC 0x0
-#define SCSI_REQUEST_SENSE_OPC 0x3
-#define SCSI_SEND_DIAGNOSTIC_OPC 0x1d
-#define SCSI_RECEIVE_DIAGNOSTIC_OPC 0x1c
#define SCSI_MAINT_IN_OPC 0xa3
-#define SCSI_REP_SUP_OPCS_OPC 0xc
-#define SCSI_REP_SUP_TMFS_OPC 0xd
#define SCSI_MODE_SENSE10_OPC 0x5a
#define SCSI_MODE_SELECT10_OPC 0x55
+#define SCSI_READ_CAPACITY10_OPC 0x25
+#define SCSI_RECEIVE_DIAGNOSTIC_OPC 0x1c
+#define SCSI_REP_SUP_OPCS_OPC 0xc
+#define SCSI_REP_SUP_TMFS_OPC 0xd
+#define SCSI_REPORT_LUNS_OPC 0xa0
+#define SCSI_REQUEST_SENSE_OPC 0x3
+#define SCSI_SEND_DIAGNOSTIC_OPC 0x1d
+#define SCSI_TEST_UNIT_READY_OPC 0x0
+#define SCSI_SERVICE_ACT_IN_OPC 0x9e
+#define SCSI_READ_CAPACITY16_SA 0x10
+#define SCSI_SA_MSK 0x1f
/* Additional Sense Code (ASC) */
#define NO_ADDITIONAL_SENSE 0x0
@@ -1294,30 +1297,22 @@ sntl_check_enclosure_override(struct freebsd_dev_channel * fdc_p, int vb)
}
}
-/* Currently only caches associated controller response (4096 bytes) */
static int
-sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
+sntl_do_identify(struct freebsd_dev_channel * fdc_p, int cns, int nsid,
+ int u_len, uint8_t * up, int vb)
{
int err;
struct nvme_pt_command npc;
uint8_t * npc_up = (uint8_t *)&npc;
- uint32_t pg_sz = sg_get_page_size();
- fdc_p->nvme_id_ctlp = sg_memalign(pg_sz, pg_sz,
- &fdc_p->free_nvme_id_ctlp, vb > 3);
- if (NULL == fdc_p->nvme_id_ctlp) {
- pr2ws("%s: sg_memalign() failed to get memory\n", __func__);
- return -ENOMEM;
- }
memset(npc_up, 0, sizeof(npc));
npc_up[SG_NVME_PT_OPCODE] = 0x6; /* Identify */
- sg_put_unaligned_le32(0x0, npc_up + SG_NVME_PT_NSID);
+ sg_put_unaligned_le32(nsid, npc_up + SG_NVME_PT_NSID);
/* CNS=0x1 Identify: controller */
- sg_put_unaligned_le32(0x1, npc_up + SG_NVME_PT_CDW10);
- sg_put_unaligned_le64((sg_uintptr_t)fdc_p->nvme_id_ctlp,
- npc_up + SG_NVME_PT_ADDR);
- sg_put_unaligned_le32(pg_sz, npc_up + SG_NVME_PT_DATA_LEN);
- err = nvme_pt_low(fdc_p, fdc_p->nvme_id_ctlp, pg_sz, true, &npc, vb);
+ sg_put_unaligned_le32(cns, npc_up + SG_NVME_PT_CDW10);
+ sg_put_unaligned_le64((sg_uintptr_t)up, npc_up + SG_NVME_PT_ADDR);
+ sg_put_unaligned_le32(u_len, npc_up + SG_NVME_PT_DATA_LEN);
+ err = nvme_pt_low(fdc_p, up, u_len, true, &npc, vb);
if (err) {
if (err < 0) {
if (vb > 1)
@@ -1329,10 +1324,29 @@ sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
return SG_LIB_NVME_STATUS;
}
}
- sntl_check_enclosure_override(fdc_p, vb);
return 0;
}
+/* Currently only caches associated controller response (4096 bytes) */
+static int
+sntl_cache_identity(struct freebsd_dev_channel * fdc_p, int vb)
+{
+ int ret;
+ uint32_t pg_sz = sg_get_page_size();
+
+ fdc_p->nvme_id_ctlp = sg_memalign(pg_sz, pg_sz,
+ &fdc_p->free_nvme_id_ctlp, vb > 3);
+ if (NULL == fdc_p->nvme_id_ctlp) {
+ pr2ws("%s: sg_memalign() failed to get memory\n", __func__);
+ return -ENOMEM;
+ }
+ ret = sntl_do_identify(fdc_p, 0x1 /* CNS */, 0 /* nsid */, pg_sz,
+ fdc_p->nvme_id_ctlp, vb);
+ if (0 == ret)
+ sntl_check_enclosure_override(fdc_p, vb);
+ return (ret < 0) ? sg_convert_errno(-ret) : ret;
+}
+
static const char * nvme_scsi_vendor_str = "NVMe ";
static const uint16_t inq_resp_len = 36;
@@ -2126,10 +2140,93 @@ sntl_rep_tmfs(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
return 0;
}
+/* Note that the "Returned logical block address" (RLBA) field in the SCSI
+ * READ CAPACITY (10+16) command's response provides the address of the _last_
+ * LBA (counting origin 0) which will be one less that the "size" in the
+ * NVMe Identify command response's NSZE field. One problem is that in
+ * some situations NSZE can be zero: temporarily set RLBA field to 0
+ * (implying a 1 LB logical units size) pending further research. The LBLIB
+ * is the "Logical Block Length In Bytes" field in the RCAP response. */
+static int
+sntl_readcap(struct sg_pt_freebsd_scsi * ptp, const uint8_t * cdbp, int vb)
+{
+ bool is_rcap10 = (SCSI_READ_CAPACITY10_OPC == cdbp[0]);
+ int res, n, len, alloc_len, dps;
+ uint8_t flbas, index, lbads; /* NVMe: 2**LBADS --> Logical Block size */
+ uint32_t lbafx; /* NVME: LBAF0...LBAF15, each 16 bytes */
+ uint32_t pg_sz = sg_get_page_size();
+ uint64_t nsze;
+ uint8_t * bp;
+ uint8_t * up;
+ uint8_t * free_up = NULL;
+ struct freebsd_dev_channel * fdc_p;
+ uint8_t resp[32];
+
+ if (vb > 3)
+ pr2ws("%s: RCAP%d\n", __func__, (is_rcap10 ? 10 : 16));
+ fdc_p = get_fdc_p(ptp);
+ if (NULL == fdc_p) {
+ pr2ws("%s: get_fdc_p() failed, no file descriptor ?\n", __func__);
+ return -EINVAL;
+ }
+ up = sg_memalign(pg_sz, pg_sz, &free_up, false);
+ if (NULL == up) {
+ pr2ws("%s: sg_memalign() failed to get memory\n", __func__);
+ return sg_convert_errno(ENOMEM);
+ }
+ res = sntl_do_identify(fdc_p, 0x0 /* CNS */, fdc_p->nsid, pg_sz, up,
+ vb);
+ if (res < 0) {
+ res = sg_convert_errno(-res);
+ goto fini;
+ }
+ memset(resp, 0, sizeof(resp));
+ nsze = sg_get_unaligned_le64(up + 0);
+ flbas = up[26]; /* NVME FLBAS field from Identify, want LBAF[flbas] */
+ index = 128 + (4 * (flbas & 0xf));
+ lbafx = sg_get_unaligned_le32(up + index);
+ lbads = (lbafx >> 16) & 0xff; /* bits 16 to 23 inclusive, pow2 */
+ if (is_rcap10) {
+ alloc_len = 8; /* implicit, not in cdb */
+ if (nsze > 0xffffffff)
+ sg_put_unaligned_be32(0xffffffff, resp + 0);
+ else if (0 == nsze) /* no good answer here */
+ sg_put_unaligned_be32(0, resp + 0); /* SCSI RLBA field */
+ else
+ sg_put_unaligned_be32((uint32_t)(nsze - 1), resp + 0);
+ sg_put_unaligned_be32(1 << lbads, resp + 4); /* SCSI LBLIB field */
+ } else {
+ alloc_len = sg_get_unaligned_be32(cdbp + 10);
+ dps = up[29];
+ if (0x7 & dps) {
+ resp[12] = 0x1;
+ n = (0x7 & dps) - 1;
+ if (n > 0)
+ resp[12] |= (n + n);
+ }
+ if (0 == nsze) /* no good answer here */
+ sg_put_unaligned_be64(0, resp + 0);
+ else
+ sg_put_unaligned_be64(nsze - 1, resp + 0);
+ sg_put_unaligned_be32(1 << lbads, resp + 8); /* SCSI LBLIB field */
+ }
+ len = ptp->dxfer_len;
+ bp = ptp->dxferp;
+ n = 32;
+ n = (n < alloc_len) ? n : alloc_len;
+ n = (n < len) ? n : len;
+ ptp->resid = len - n;
+ if (n > 0)
+ memcpy(bp, resp, n);
+fini:
+ if (free_up)
+ free(free_up);
+ return res;
+}
+
/* Executes NVMe Admin command (or at least forwards it to lower layers).
* Returns 0 for success, negative numbers are negated 'errno' values from
- * OS system calls. Positive return values are errors from this package.
- * The time_secs argument is ignored. */
+ * OS system calls. Positive return values are errors from this package. */
static int
sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
{
@@ -2205,6 +2302,12 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
case SCSI_MODE_SENSE10_OPC:
case SCSI_MODE_SELECT10_OPC:
return sntl_mode_ss(ptp, cdbp, vb);
+ case SCSI_READ_CAPACITY10_OPC:
+ return sntl_readcap(ptp, cdbp, vb);
+ case SCSI_SERVICE_ACT_IN_OPC:
+ if (SCSI_READ_CAPACITY16_SA == (cdbp[1] & SCSI_SA_MSK))
+ return sntl_readcap(ptp, cdbp, vb);
+ goto fini;
case SCSI_MAINT_IN_OPC:
sa = 0x1f & cdbp[1]; /* service action */
if (SCSI_REP_SUP_OPCS_OPC == sa)
@@ -2213,6 +2316,7 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int vb)
return sntl_rep_tmfs(ptp, cdbp, vb);
/* fall through */
default:
+fini:
if (vb > 2) {
char b[64];
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index a2eeb6da..6c49096b 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2020 Douglas Gilbert.
+ * Copyright (c) 2005-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.
@@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-/* sg_pt_linux version 1.50 20201123 */
+/* sg_pt_linux version 1.51 20210102 */
#include <stdio.h>
@@ -794,7 +794,7 @@ get_scsi_pt_resid(const struct sg_pt_base * vp)
{
const struct sg_pt_linux_scsi * ptp = &vp->impl;
- if ((NULL == ptp) || (! ptp->nvme_our_sntl))
+ if ((NULL == ptp) || (ptp->is_nvme && ! ptp->nvme_our_sntl))
return 0;
else if ((ptp->io_hdr.din_xfer_len > 0) &&
(ptp->io_hdr.dout_xfer_len > 0))
@@ -853,8 +853,8 @@ get_scsi_pt_status_response(const struct sg_pt_base * vp)
if (NULL == ptp)
return 0;
- return (int)(ptp->nvme_our_sntl ? ptp->io_hdr.device_status :
- ptp->nvme_status);
+ return (int)((ptp->is_nvme && ! ptp->nvme_our_sntl) ?
+ ptp->nvme_status : ptp->io_hdr.device_status);
}
uint32_t
@@ -864,7 +864,8 @@ get_pt_result(const struct sg_pt_base * vp)
if (NULL == ptp)
return 0;
- return ptp->nvme_our_sntl ? ptp->io_hdr.device_status : ptp->nvme_result;
+ return (ptp->is_nvme && ! ptp->nvme_our_sntl) ?
+ ptp->nvme_result : ptp->io_hdr.device_status;
}
int
@@ -1152,6 +1153,9 @@ do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose)
}
if (ptp->os_err)
return -ptp->os_err;
+ if (verbose > 5)
+ pr2ws("%s: is_nvme=%d, is_sg=%d, is_bsg=%d\n", __func__,
+ (int)ptp->is_nvme, (int)ptp->is_sg, (int)ptp->is_bsg);
if (ptp->is_nvme)
return sg_do_nvme_pt(vp, -1, time_secs, verbose);
else if (ptp->is_sg) {
diff --git a/lib/sg_pt_linux_nvme.c b/lib/sg_pt_linux_nvme.c
index ea71c7b1..74453f74 100644
--- a/lib/sg_pt_linux_nvme.c
+++ b/lib/sg_pt_linux_nvme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Douglas Gilbert.
+ * Copyright (c) 2017-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.
@@ -41,7 +41,7 @@
* MA 02110-1301, USA.
*/
-/* sg_pt_linux_nvme version 1.14 20201123 */
+/* sg_pt_linux_nvme version 1.15 20210102 */
/* This file contains a small "SPC-only" SNTL to support the SES pass-through
* of SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS through NVME-MI
@@ -464,7 +464,7 @@ sntl_do_identify(struct sg_pt_linux_scsi * ptp, int cns, int nsid,
/* Currently only caches associated identify controller response (4096 bytes).
* Returns 0 on success; otherwise a positive value is returned */
static int
-sntl_cache_identity(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
+sntl_cache_identify(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
{
int ret;
uint32_t pg_sz = sg_get_page_size();
@@ -536,7 +536,7 @@ sntl_inq(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs,
return 0;
}
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
@@ -683,7 +683,7 @@ sntl_rluns(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs,
sel_report = cdbp[2];
alloc_len = sg_get_unaligned_be32(cdbp + 6);
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
@@ -743,7 +743,7 @@ sntl_tur(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
if (vb > 4)
pr2ws("%s: start\n", __func__);
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
@@ -782,7 +782,7 @@ sntl_req_sense(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
if (vb > 3)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
@@ -835,7 +835,7 @@ sntl_mode_ss(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
if (vb > 3)
pr2ws("%s: mode se%s\n", __func__, (is_msense ? "nse" : "lect"));
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
@@ -1256,7 +1256,7 @@ sntl_rep_tmfs(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
* is the "Logical Block Length In Bytes" field in the RCAP response. */
static int
sntl_readcap(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
- int time_secs, int vb)
+ int time_secs, int vb)
{
bool is_rcap10 = (SCSI_READ_CAPACITY10_OPC == cdbp[0]);
int res, n, len, alloc_len, dps;
@@ -1283,7 +1283,7 @@ sntl_readcap(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
res = sg_convert_errno(-res);
goto fini;
}
- memset(resp, 0, sizeof(*resp));
+ memset(resp, 0, sizeof(resp));
nsze = sg_get_unaligned_le64(up + 0);
flbas = up[26]; /* NVME FLBAS field from Identify, want LBAF[flbas] */
index = 128 + (4 * (flbas & 0xf));
@@ -1315,7 +1315,7 @@ sntl_readcap(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
len = ptp->io_hdr.din_xfer_len;
bp = (uint8_t *)(sg_uintptr_t)ptp->io_hdr.din_xferp;
- n = 16;
+ n = 32;
n = (n < alloc_len) ? n : alloc_len;
n = (n < len) ? n : len;
ptp->io_hdr.din_resid = len - n;
@@ -1614,7 +1614,7 @@ sntl_write_same(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
if (dp == NULL)
return sg_convert_errno(ENOMEM);
if (NULL == ptp->nvme_id_ctlp) {
- res = sntl_cache_identity(ptp, time_secs, vb);
+ res = sntl_cache_identify(ptp, time_secs, vb);
if (SG_LIB_NVME_STATUS == res) {
mk_sense_from_nvme_status(ptp, vb);
return 0;
diff --git a/lib/sg_pt_win32.c b/lib/sg_pt_win32.c
index 5bab5c2f..cc56a26d 100644
--- a/lib/sg_pt_win32.c
+++ b/lib/sg_pt_win32.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2020 Douglas Gilbert.
+ * Copyright (c) 2006-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.
@@ -7,7 +7,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-/* sg_pt_win32 version 1.32 20201207 */
+/* sg_pt_win32 version 1.33 20210103 */
#include <stdio.h>
#include <stdlib.h>
@@ -2142,7 +2142,7 @@ do_nvme_admin_cmd(struct sg_pt_win32_scsi * psp, struct sg_pt_handle * shp,
get_err_str(n, sizeof(b), b), n);
}
}
- /* nvme_status is SCT|SC, therefor it excludes DNR+More */
+ /* nvme_status is SCT|SC, therefore it excludes DNR+More */
psp->nvme_status = 0x3ff & (pthru->CplEntry[3] >> 17);
if (psp->nvme_status && (vb > 1)) {
uint16_t s = psp->nvme_status;
diff --git a/scripts/fc_wwpn_id b/scripts/fc_wwpn_id
index c8d01892..17c74fe8 100644
--- a/scripts/fc_wwpn_id
+++ b/scripts/fc_wwpn_id
@@ -3,7 +3,7 @@
# fc_wwpn_id
#
# Generates device node names links based on FC WWPN
-# Copyright (c) 2016 Hannes Reinecke, SUSE Linux GmbH
+# Copyright (c) 2016-2021 Hannes Reinecke, SUSE Linux GmbH
#
# 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
@@ -38,7 +38,9 @@ while [ -n "$d" ] ; do
esac
done
-echo "FC_TARGET_LUN=$target_lun"
+if [ -n "$rport_wwpn" ] || [ -n "$host_wwpn" ] ; then
+ echo "FC_TARGET_LUN=$target_lun"
+fi
if [ -n "$rport_wwpn" ] ; then
echo "FC_TARGET_WWPN=$rport_wwpn"
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 9dd875cc..8a0a9dbf 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Sat Dec 05 2020 - dgilbert at interlog dot com
+* Sun Jan 03 2021 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.46
diff --git a/src/Makefile.am b/src/Makefile.am
index c6581efa..46d34665 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
+# AM_CFLAGS = -Wall -W -pedantic -std=c++20
sg_bg_ctl_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index 2ec6a12b..cd146ae6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -634,6 +634,7 @@ AM_CFLAGS = -Wall -W $(DBG_CFLAGS)
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
+# AM_CFLAGS = -Wall -W -pedantic -std=c++20
sg_bg_ctl_LDADD = ../lib/libsgutils2.la
sg_compare_and_write_LDADD = ../lib/libsgutils2.la
sg_copy_results_LDADD = ../lib/libsgutils2.la
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 2dff65b8..ddf216d1 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -1,7 +1,7 @@
/*
* A utility program originally written for the Linux OS SCSI subsystem.
*
- * Copyright (C) 2000-2020 Ingo van Lil <inguin@gmx.de>
+ * Copyright (C) 2000-2021 Ingo van Lil <inguin@gmx.de>
*
* 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
@@ -39,7 +39,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.33 (2020-08-02)"
+#define SG_RAW_VERSION "0.4.34 (2021-01-03)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -54,6 +54,7 @@
static struct option long_options[] = {
{ "binary", no_argument, NULL, 'b' },
{ "cmdfile", required_argument, NULL, 'c' },
+ { "cmdset", required_argument, NULL, 'C' },
{ "enumerate", no_argument, NULL, 'e' },
{ "help", no_argument, NULL, 'h' },
{ "infile", required_argument, NULL, 'i' },
@@ -64,6 +65,7 @@ static struct option long_options[] = {
{ "raw", no_argument, NULL, 'w' },
{ "request", required_argument, NULL, 'r' },
{ "readonly", no_argument, NULL, 'R' },
+ { "scan", required_argument, NULL, 'Q' },
{ "send", required_argument, NULL, 's' },
{ "timeout", required_argument, NULL, 't' },
{ "verbose", no_argument, NULL, 'v' },
@@ -83,11 +85,14 @@ struct opts_t {
bool verbose_given;
bool version_given;
int cdb_length;
+ int cmdset;
int datain_len;
int dataout_len;
int timeout;
int raw;
int readonly;
+ int scan_first;
+ int scan_last;
int verbose;
off_t dataout_offset;
uint8_t cdb[MAX_SCSI_CDBSZ]; /* might be NVMe command (64 byte) */
@@ -102,7 +107,7 @@ static void
pr_version()
{
pr2serr("sg_raw " SG_RAW_VERSION "\n"
- "Copyright (C) 2007-2020 Ingo van Lil <inguin@gmx.de>\n"
+ "Copyright (C) 2007-2021 Ingo van Lil <inguin@gmx.de>\n"
"This is free software. You may redistribute copies of it "
"under the terms of\n"
"the GNU General Public License "
@@ -121,6 +126,9 @@ usage()
" stdout\n"
" --cmdfile=CF|-c CF CF is file containing command in hex "
"bytes\n"
+ " --cmdset=CS|-C CS CS is 0 (def) heuristic chooses "
+ "command set;\n"
+ " 1: force SCSI; 2: force NVMe\n"
" --enumerate|-e Decodes cdb name then exits; requires "
"DEVICE but\n"
" ignores it\n"
@@ -129,9 +137,10 @@ usage()
"(default:\n"
" stdin)\n"
" --nosense|-n Don't display sense information\n"
- " --nvm|-N command is for NVM command set (def: "
- "if NVMe fd:\n"
- " Admin command set)\n"
+ " --nvm|-N command is for NVM command set (e.g. "
+ "Read);\n"
+ " default, if NVMe fd, Admin command "
+ "set\n"
" --outfile=OFILE|-o OFILE Write binary data to OFILE (def: "
"hexdump\n"
" to stdout)\n"
@@ -142,6 +151,11 @@ usage()
"read-write)\n"
" --request=RLEN|-r RLEN Request up to RLEN bytes of data "
"(data-in)\n"
+ " --scan=FO,LO|-Q FO,LO scan command set from FO (first "
+ "opcode)\n"
+ " to LO (last opcode) inclusive. Uses "
+ "given\n"
+ " command bytes, varying the opcode\n"
" --send=SLEN|-s SLEN Send SLEN bytes of data (data-out)\n"
" --skip=KLEN|-k KLEN Skip the first KLEN bytes when "
"reading\n"
@@ -162,9 +176,10 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
{
while (1) {
int c, n;
+ const char * cp;
- c = getopt_long(argc, argv, "bc:ehi:k:nNo:r:Rs:t:vVw", long_options,
- NULL);
+ c = getopt_long(argc, argv, "bc:C:ehi:k:nNo:Q:r:Rs:t:vVw",
+ long_options, NULL);
if (c == -1)
break;
@@ -176,6 +191,14 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
op->cmd_file = optarg;
op->cmdfile_given = true;
break;
+ case 'C':
+ n = sg_get_num(optarg);
+ if ((n < 0) || (n > 2)) {
+ pr2serr("Invalid argument to --cmdset= expect 0, 1 or 2\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->cmdset = n;
+ break;
case 'e':
op->do_enumerate = true;
break;
@@ -211,6 +234,27 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
}
op->datain_file = optarg;
break;
+ case 'Q': /* --scan=FO,LO */
+ cp = strchr(optarg, ',');
+ if (NULL == cp) {
+ pr2serr("--scan= expects two numbers, comma separated\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ n = sg_get_num(optarg);
+ if ((n < 0) || (n > 255)) {
+ pr2serr("Invalid first number to --scan= expect 0 to 255\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->scan_first = n;
+ n = sg_get_num(cp + 1);
+ if ((n < 0) || (n > 255)) {
+ pr2serr("Invalid second number to --scan= expect 0 to 255\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->scan_last = n;
+ if (op->scan_first >= n)
+ pr2serr("Warning: scan range degenerate, ignore\n");
+ break;
case 'r':
op->do_datain = true;
n = sg_get_num(optarg);
@@ -262,6 +306,13 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
op->device_name = argv[optind];
++optind;
+ if (op->version_given
+#ifdef DEBUG
+ && ! op->verbose_given
+#endif
+ )
+ return 0;
+
while (optind < argc) {
char *opt = argv[optind++];
char *endptr;
@@ -305,6 +356,16 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
int sa;
char b[80];
+ if ((1 == op->cmdset) && !is_scsi_cdb) {
+ is_scsi_cdb = true;
+ if (op->verbose > 3)
+ printf(">>> overriding cmdset guess to SCSI\n");
+ }
+ if ((2 == op->cmdset) && is_scsi_cdb) {
+ is_scsi_cdb = false;
+ if (op->verbose > 3)
+ printf(">>> overriding cmdset guess to NVMe\n");
+ }
if (is_scsi_cdb) {
if (op->cdb_length > 16) {
sa = sg_get_unaligned_be16(op->cdb + 8);
@@ -472,6 +533,7 @@ int
main(int argc, char *argv[])
{
bool is_scsi_cdb = true;
+ bool do_scan = false;
int ret = 0;
int err = 0;
int res_cat, status, s_len, k, ret2;
@@ -538,7 +600,24 @@ main(int argc, char *argv[])
goto done;
}
+ if (op->scan_first < op->scan_last)
+ do_scan = true;
+
+and_again:
+ if (do_scan) {
+ op->cdb[0] = op->scan_first;
+ printf("Command bytes in hex:");
+ for (k = 0; k < op->cdb_length; ++k)
+ printf(" %02x", op->cdb[k]);
+ printf("\n");
+ }
+
is_scsi_cdb = sg_is_scsi_cdb(op->cdb, op->cdb_length);
+ if ((1 == op->cmdset) && !is_scsi_cdb)
+ is_scsi_cdb = true;
+ else if ((2 == op->cmdset) && is_scsi_cdb)
+ is_scsi_cdb = false;
+
if (op->do_dataout) {
uint32_t dout_len;
@@ -743,6 +822,14 @@ main(int argc, char *argv[])
}
done:
+ if (do_scan) {
+ ++op->scan_first;
+ if (op->scan_first <= op->scan_last) {
+ clear_scsi_pt_obj(ptvp);
+ goto and_again;
+ }
+ }
+
if (op->verbose && is_scsi_cdb) {
sg_get_category_sense_str(ret, b_len, b, op->verbose - 1);
pr2serr("%s\n", b);
diff --git a/src/sg_turs.c b/src/sg_turs.c
index 88075a4f..9544e344 100644
--- a/src/sg_turs.c
+++ b/src/sg_turs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2020 D. Gilbert
+ * Copyright (C) 2000-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)
@@ -45,7 +45,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "3.47 20200722";
+static const char * version_str = "3.48 20210102";
#define DEF_PT_TIMEOUT 60 /* 60 seconds */
@@ -264,7 +264,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->version_given = true;
break;
case '?':
- usage_old();
+ ++op->do_help;
return 0;
default:
jmp_out = true;
diff --git a/src/sgp_dd.c b/src/sgp_dd.c
index 3975f038..cda52d3b 100644
--- a/src/sgp_dd.c
+++ b/src/sgp_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)
@@ -84,7 +84,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "5.76 20200510";
+static const char * version_str = "5.77 20210103";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -229,14 +229,17 @@ static atomic_uint ascending_val;
static pthread_mutex_t av_mut = PTHREAD_MUTEX_INITIALIZER;
static int ascending_val = 1;
-#define GET_NEXT_PACK_ID(_v) \
- ( { int _r; \
- do { \
- pthread_mutex_lock(&av_mut); \
- _r = ascending_val; \
- ascending_val += _v; \
- pthread_mutex_lock(&av_mut); \
- } while (0) ; _r; } )
+static unsigned int
+GET_NEXT_PACK_ID(unsigned int val)
+{
+ int res;
+
+ pthread_mutex_lock(&av_mut);
+ res = ascending_val;
+ ascending_val += val;
+ pthread_mutex_unlock(&av_mut);
+ return res;
+}
#endif
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index fc793dca..aa20c219 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -12,9 +12,9 @@
* Copyright (C) 1992 Lawrence Foard
*
* Later extensions (versions 2, 3 and 4) to driver:
- * Copyright (C) 1998 - 2020 Douglas Gilbert
+ * Copyright (C) 1998 - 2021 Douglas Gilbert
*
- * Version 4.0.45 (20200913)
+ * Version 4.0.46 (20210101)
* This version is for Linux 4 and 5 series kernels.
*
* Documentation
@@ -129,6 +129,7 @@ typedef struct sg_io_hdr {
#define SGV4_FLAG_EVENTFD 0x40000 /* signal completion on ... */
#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_HIPRI 0x200000 /* completion via SG_SEIM_BLK_POLL */
/* Output (potentially OR-ed together) in v3::info or v4::info field */
#define SG_INFO_OK_MASK 0x1
@@ -199,7 +200,8 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
#define SG_SEIM_CHG_SHARE_FD 0x40 /* read-side given new write-side fd */
#define SG_SEIM_SGAT_ELEM_SZ 0x80 /* sgat element size (>= PAGE_SIZE) */
#define SG_SEIM_EVENTFD 0x100 /* pass eventfd to driver */
-#define SG_SEIM_ALL_BITS 0x1ff /* should be OR of previous items */
+#define SG_SEIM_BLK_POLL 0x200 /* call blk_poll, uses general field */
+#define SG_SEIM_ALL_BITS 0x3ff /* should be OR of previous items */
/* flag and mask values for boolean fields follow */
#define SG_CTL_FLAGM_TIME_IN_NS 0x1 /* time: nanosecs (def: millisecs) */
@@ -260,7 +262,9 @@ struct sg_extended_info {
__u32 minor_index; /* rd: kernel's sg device minor number */
__u32 share_fd; /* for SHARE_FD, CHG_SHARE_FD or EVENTFD */
__u32 sgat_elem_sz; /* sgat element size (must be power of 2) */
- __u8 pad_to_96[52]; /* pad so struct is 96 bytes long */
+ __s32 num; /* blk_poll: spin for num (0: no spin); raw */
+ /* read number completed */
+ __u8 pad_to_96[48]; /* pad so struct is 96 bytes long */
};
/*