aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-06-05 16:19:48 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-06-05 16:19:48 +0000
commit62c85c807d9d57f6bcf9a731d0126feaab661d93 (patch)
tree8ac564376084a4b96c3276db911c298f86c4232b
parenteda62fa0cd1d5886bd9893ba2831a37c5e24d4c7 (diff)
downloadsg3_utils-62c85c807d9d57f6bcf9a731d0126feaab661d93.tar.gz
sg_rep_pip: new utility; testing/sg_tst_ioctl.c work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@852 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--COVERAGE1
-rw-r--r--ChangeLog3
-rw-r--r--README24
-rw-r--r--README.freebsd3
-rw-r--r--README.solaris3
-rw-r--r--README.win323
-rw-r--r--debian/changelog2
-rw-r--r--doc/Makefile.am12
-rw-r--r--doc/Makefile.in17
-rw-r--r--doc/sg3_utils.82
-rw-r--r--doc/sg_rep_pip.858
-rw-r--r--doc/sg_rep_zones.88
-rw-r--r--doc/sg_write_same.836
-rw-r--r--doc/sg_write_x.88
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.in54
-rw-r--r--src/sg_rep_pip.c325
-rw-r--r--testing/sg_tst_ioctl.c124
19 files changed, 604 insertions, 89 deletions
diff --git a/COVERAGE b/COVERAGE
index b7feb2ae..830bfe05 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -74,6 +74,7 @@ RECEIVE ROD TOKEN INFORMATION ddpt, ddptctl ++
REPORT ALL ROD TOKENS ddptctl ++
REPORT IDENTIFYING INFORMATION sg_ident, ++ (2)
REPORT LUNS sg_luns, ++
+REPORT PROVISIONING INITIALIZATION PATTERN sg_rep_pip, ++
REPORT REFERRALS sg_referrals, ++
REPORT SUPPORTED OPERATION CODES sg_opcodes
REPORT SUPPORTED TASK MANAGEMENT FUNCTIONS sg_opcodes
diff --git a/ChangeLog b/ChangeLog
index fc9fe37c..b98b0420 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,8 @@ 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 [20200513] [svn: r851]
+Changelog for sg3_utils-1.46 [20200604] [svn: r852]
+ - sg_rep_pip: report new provisioning initialization pattern cmd
- sg_dd: separate category for miscompare errors
- sg_get_elem_status: add ralwd bit sbc4r20a
- sg_write_x: add dld bits to write(32) [sbc4r19a]
diff --git a/README b/README
index b88dd447..277cbe2a 100644
--- a/README
+++ b/README
@@ -263,10 +263,10 @@ subdirectory of the sg3_utils package:
sg_luns, sg_map, sg_map26, sg_modes, sg_opcodes, sg_persist, sg_prevent,
sg_raw, sg_rbuf, sg_rdac, sg_read, sg_read_attr, sg_readcap,
sg_read_block_limits, sg_read_buffer, sg_read_long, sg_reassign,
- sg_referrals, sg_request, sg_reset, sg_rmsn, sg_rtpg, sg_safte,
- sg_sanitize, sg_sat_identify, sg_sat_phy_event, sg_sat_read_gplog,
- sg_sat_set_features, sg_scan, sg_seek, sg_senddiag, sg_ses,
- sg_ses_microcode, sg_start, sg_stpg, sg_stream_ctl, sg_sync,
+ sg_referrals, sg_rep_pip, sg_rep_zones, sg_request, sg_reset, sg_rmsn,
+ sg_rtpg, sg_safte, sg_sanitize, sg_sat_identify, sg_sat_phy_event,
+ sg_sat_read_gplog, sg_sat_set_features, sg_scan, sg_seek, sg_senddiag,
+ sg_ses, sg_ses_microcode, sg_start, sg_stpg, sg_stream_ctl, sg_sync,
sg_test_rwbuff, sg_timestamp, sg_turs, sg_unmap, sg_verify, sg_vpd,
sg_write_buffer, sg_write_long, sg_write_same, sg_write_verify,
sg_write_x, sg_wr_mode, sg_xcopy, sg_zone
@@ -449,13 +449,13 @@ The more recent utilities that use "getopt_long" only are:
- sg_bt_ctl, sg_compare_and_write, sg_decode_sense, sg_format,
sg_get_config, sg_get_lba_status, sg_ident, sg_luns, sg_map26,
sg_persist, sg_prevent, sg_raw, sg_read_attr, sg_read_block_limits,
- sg_read_buffer, sg_read_long, sg_reassign, sg_referrals, sg_requests,
- sg_rmsn, sg_rtpg, sg_safte, sg_sanitize, sg_sat_identify,
- sg_sat_phy_event, sg_sat_read_gplog, sg_sat_set_features, sg_scan(w),
- sg_seek, sg_ses, sg_ses_microcode, sg_stpg, sg_stream_ctl, sg_sync,
- sg_test_rwbuf, sg_timestamp, sg_unmap, sg_verify, sg_vpd,
- sg_write_buffer, sg_write_long, sg_write_same, sg_write_verify,
- sg_write_x, sg_wr_mode, sg_zone
+ sg_read_buffer, sg_read_long, sg_reassign, sg_referrals, sg_rep_pip,
+ sg_rep_zones, sg_requests, sg_rmsn, sg_rtpg, sg_safte, sg_sanitize,
+ sg_sat_identify, sg_sat_phy_event, sg_sat_read_gplog,
+ sg_sat_set_features, sg_scan(w), sg_seek, sg_ses, sg_ses_microcode,
+ sg_stpg, sg_stream_ctl, sg_sync, sg_test_rwbuf, sg_timestamp, sg_unmap,
+ sg_verify, sg_vpd, sg_write_buffer, sg_write_long, sg_write_same,
+ sg_write_verify, sg_write_x, sg_wr_mode, sg_zone
Dangerous code
@@ -541,4 +541,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-17 September 2019
+5th June 2020
diff --git a/README.freebsd b/README.freebsd
index 4a720a79..afdd2079 100644
--- a/README.freebsd
+++ b/README.freebsd
@@ -36,6 +36,7 @@ Here is a list of utilities that have been ported:
sg_readcap
sg_reassign
sg_referrals
+ sg_rep_pip
sg_rep_zones
sg_requests
sg_rmsn
@@ -143,4 +144,4 @@ utilities.
Douglas Gilbert
-9th September 2019
+5th June 2020
diff --git a/README.solaris b/README.solaris
index dac22dc4..3fa894d3 100644
--- a/README.solaris
+++ b/README.solaris
@@ -53,6 +53,7 @@ Here is a list of utilities that have been ported:
sg_readcap
sg_reassign
sg_referrals
+ sg_rep_pip
sg_rep_zones
sg_requests
sg_rmsn
@@ -164,4 +165,4 @@ disks to accept SCSI commands including the SCSI ATA PASS THROUGH commands.
Douglas Gilbert
-9th September 2019
+5th June 2020
diff --git a/README.win32 b/README.win32
index 47115253..912bade0 100644
--- a/README.win32
+++ b/README.win32
@@ -57,6 +57,7 @@ Here is a list of utilities that have been ported:
sg_readcap
sg_reassign
sg_referrals
+ sg_rep_pip
sg_rep_zones
sg_requests
sg_reset_wp
@@ -243,4 +244,4 @@ mode" with the setmode() Windows command.
Douglas Gilbert
-9th September 2019
+6th June 2020
diff --git a/debian/changelog b/debian/changelog
index f2dd3dba..eae95a69 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> Wed, 13 May 2020 01:00:00 -0400
+ -- Douglas Gilbert <dgilbert@interlog.com> Mon, 01 Jun 2020 12:00:00 -0400
sg3-utils (1.45-0.1) unstable; urgency=low
diff --git a/doc/Makefile.am b/doc/Makefile.am
index fc8e85d3..e0dd2e64 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -7,12 +7,12 @@ man_MANS = \
sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
sg_prevent.8 sg_raw.8 sg_rdac.8 sg_read_attr.8 \
sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 sg_readcap.8 \
- sg_reassign.8 sg_referrals.8 sg_rep_zones.8 sg_requests.8 \
- sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sanitize.8 \
- sg_sat_identify.8 sg_sat_phy_event.8 sg_sat_read_gplog.8 \
- sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 sg_ses.8 \
- sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 sg_sync.8 \
- sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
+ sg_reassign.8 sg_referrals.8 sg_rep_pip.8 sg_rep_zones.8 \
+ sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 \
+ sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8
+ sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 \
+ sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 \
+ sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 sg_write_same.8 \
sg_write_verify.8 sg_write_x.8 sg_zone.8
CLEANFILES =
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 6a37b4f8..448bf3eb 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -288,14 +288,10 @@ man_MANS = scsi_mandat.8 scsi_readcap.8 scsi_ready.8 scsi_satl.8 \
sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
sg_rdac.8 sg_read_attr.8 sg_read_block_limits.8 \
sg_read_buffer.8 sg_read_long.8 sg_readcap.8 sg_reassign.8 \
- sg_referrals.8 sg_rep_zones.8 sg_requests.8 sg_reset_wp.8 \
- sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sanitize.8 sg_sat_identify.8 \
- sg_sat_phy_event.8 sg_sat_read_gplog.8 sg_sat_set_features.8 \
- sg_seek.8 sg_senddiag.8 sg_ses.8 sg_ses_microcode.8 sg_start.8 \
- sg_stpg.8 sg_stream_ctl.8 sg_sync.8 sg_timestamp.8 sg_turs.8 \
- sg_unmap.8 sg_verify.8 sg_vpd.8 sg_wr_mode.8 sg_write_buffer.8 \
- sg_write_long.8 sg_write_same.8 sg_write_verify.8 sg_write_x.8 \
- sg_zone.8 $(am__append_1) $(am__append_3) $(am__append_5)
+ sg_referrals.8 sg_rep_pip.8 sg_rep_zones.8 sg_requests.8 \
+ sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sanitize.8 \
+ sg_sat_identify.8 sg_sat_phy_event.8 $(am__append_1) \
+ $(am__append_3) $(am__append_5)
CLEANFILES = $(am__append_2) $(am__append_4) $(am__append_6)
all: all-am
@@ -541,6 +537,11 @@ uninstall-man: uninstall-man8
.PRECIOUS: Makefile
+ sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 \
+ sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 \
+ sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
+ sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 sg_write_same.8 \
+ sg_write_verify.8 sg_write_x.8 sg_zone.8
@OS_LINUX_TRUE@sg_scan.8: sg_scan.8.linux
@OS_LINUX_TRUE@ cp -p $< $@
@OS_WIN32_MINGW_TRUE@sg_scan.8: sg_scan.8.win32
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index de3106b3..fd0f7991 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "May 2020" "sg3_utils\-1.46" SG3_UTILS
+.TH SG3_UTILS "8" "June 2020" "sg3_utils\-1.46" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
diff --git a/doc/sg_rep_pip.8 b/doc/sg_rep_pip.8
new file mode 100644
index 00000000..81dd060d
--- /dev/null
+++ b/doc/sg_rep_pip.8
@@ -0,0 +1,58 @@
+.TH SG_REP_PIP "8" "June 2020" "sg3_utils\-1.46" SG3_UTILS
+.SH NAME
+sg_rep_pip \- send SCSI REPORT PROVISIONING INITIALIZATION PATTERN command
+.SH SYNOPSIS
+.B sg_rep_pip
+[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-raw\fR]
+[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR]
+\fIDEVICE\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+Sends a SCSI REPORT PROVISIONING INITIALIZATION PATTERN command to
+\fIDEVICE\fR and outputs the data returned. This command is found in the
+SBC\-4 draft standard, revision 21 (sbc\4r21.pdf).
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+output the usage message then exit.
+.TP
+\fB\-H\fR, \fB\-\-hex\fR
+output the response in hexadecimal to stdout. When used once the whole
+response is output in ASCII hexadecimal with a leading address (starting at
+0) on each line. When used twice the whole response is output in hexadecimal
+with no leading address (on each line). The default action is the same as
+giving the \fI\-\-hex\fR option once.
+.TP
+\fB\-m\fR, \fB\-\-maxlen\fR=\fILEN\fR
+where \fILEN\fR is the (maximum) response length in bytes. It is placed in
+the cdb's "allocation length" field. If not given (or \fILEN\fR is zero)
+then 8192 is used. The maximum allowed value of \fILEN\fR is 1048576.
+.TP
+\fB\-r\fR, \fB\-\-raw\fR
+output the SCSI response (i.e. the data\-out buffer) in binary (to stdout).
+.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
+The default is to open it read\-write.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+increase the level of verbosity, (i.e. debug output).
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.SH EXIT STATUS
+The exit status of sg_rep_pip is 0 when it is successful. Otherwise see
+the sg3_utils(8) man page.
+.SH AUTHORS
+Written by Douglas Gilbert.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2020 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.
+.SH "SEE ALSO"
+.B sg3_utils(sg3_utils)
diff --git a/doc/sg_rep_zones.8 b/doc/sg_rep_zones.8
index 29fecd19..cf810799 100644
--- a/doc/sg_rep_zones.8
+++ b/doc/sg_rep_zones.8
@@ -1,4 +1,4 @@
-.TH SG_REP_ZONES "8" "February 2020" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_REP_ZONES "8" "June 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_rep_zones \- send SCSI REPORT ZONES command
.SH SYNOPSIS
@@ -68,12 +68,12 @@ prefixed with '0x' or has a trailing 'h' which indicate hexadecimal.
increase the level of verbosity, (i.e. debug output).
.TP
\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.TP
+\fB\-w\fR, \fB\-\-wp\fR
print the write pointer (in hex) only. In the absence of errors, then a hex
LBA will be printed on each line, one line for each zone. Can be usefully
combined with the \fI\-\-num=NUM\fR and \fI\-\-start=LBA\fR options.
-.TP
-\fB\-w\fR, \fB\-\-wp\fR
-print the version string and then exit.
.SH EXIT STATUS
The exit status of sg_rep_zones is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
diff --git a/doc/sg_write_same.8 b/doc/sg_write_same.8
index 55dcfec9..1a9d4fff 100644
--- a/doc/sg_write_same.8
+++ b/doc/sg_write_same.8
@@ -1,4 +1,4 @@
-.TH SG_WRITE_SAME "8" "December 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_WRITE_SAME "8" "June 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_write_same \- send SCSI WRITE SAME command
.SH SYNOPSIS
@@ -124,6 +124,10 @@ sets the NDOB bit in the WRITE SAME (16 and 32 byte) commands. NDOB stands
for No Data\-Out Buffer. Default is to clear this bit. When this option
is given then \fI\-\-in=IF\fR is not allowed and \fI\-\-xferlen=LEN\fR can
only be given if \fILEN\fR is 0 .
+.br
+By default zeros are written in each block, but it is possible that
+the "provisioning initialization pattern" is written depending on other
+settings.
.TP
\fB\-n\fR, \fB\-\-num\fR=\fINUM\fR
where \fINUM\fR is the number of blocks, starting at \fILBA\fR, to write the
@@ -235,7 +239,11 @@ introduction in lk 2.6.28 .
The exit status of sg_write_same is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
.SH EXAMPLES
-One simple usage is to write blocks of zero from (and including) a given LBA:
+BEWARE: all these examples will overwrite the data on one or more blocks,
+potentially CLEARING the WHOLE DISK.
+.PP
+One simple usage is to write blocks of zero from (and including) a given LBA
+for 63 blocks:
.PP
sg_write_same \-\-lba=0x1234 \-\-num=63 /dev/sdc
.PP
@@ -246,7 +254,24 @@ of bytes in a logical block. Let us assume that is 512 bytes. Since
of zeros (each block containing 512 bytes) will be written from (and
including) LBA 0x1234 . Note that only one block of zeros is passed
to the SCSI WRITE SAME command in the data\-out buffer (as required by
-SBC\-3).
+SBC\-3). Using the WRITE SAME SCSI command to write one or more blocks
+blocks of zeros is equivalent to the NVMe command: Write Zeroes.
+.br
+Now we will write zero blocks to the WHOLE disk. [Note sanitize type
+commands will also clear blocks and metdata that are not directly
+visible]:
+.PP
+ sg_write_same \-\-lba=0x0 \-\-num=0 /dev/sdc
+.PP
+Yes, in this context \-\-num=0 means the rest of the disk. The above
+invocation may give an error due to the WSNZ bit in the Block Limits VPD
+page being set. To get around that try:
+.PP
+ sg_write_same \-\-lba=0x0 \-\-ndob /dev/sdc
+.PP
+this invocation, if supported, has the added benefit of not sending a data
+out buffer of zeros. Notes that it is possible that the "provisioning
+initialization pattern" is written to each block instead of zeros.
.PP
A similar example follows but in this case the blocks
are "unmapped" ("trimmed" in ATA speak) rather than zeroed:
@@ -322,9 +347,10 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2009\-2019 Douglas Gilbert
+Copyright \(co 2009\-2020 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.
.SH "SEE ALSO"
-.B sg_format,sg_get_lba_status,sg_readcap,sg_vpd,sg_unmap(sg3_utils)
+.B sg_format,sg_get_lba_status,sg_readcap,sg_vpd,sg_unmap,
+.B sg_write_x(sg3_utils)
diff --git a/doc/sg_write_x.8 b/doc/sg_write_x.8
index de9f10da..95352aae 100644
--- a/doc/sg_write_x.8
+++ b/doc/sg_write_x.8
@@ -1,4 +1,4 @@
-.TH SG_WRITE_X "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_WRITE_X "8" "June 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_write_x \- SCSI WRITE normal/ATOMIC/SAME/SCATTERED/STREAM, ORWRITE commands
.SH SYNOPSIS
@@ -137,7 +137,7 @@ The current reference for these commands is draft SBC\-4 (T10/BSR INCITS
506) revision 15 dated 9 November 2017. All six SCSI commands are described
in that document. WRITE ATOMIC was added in SBC\-4 revision 3; WRITE STREAM
was added in SBC\-4 revision 7; WRITE SCATTERED was added in SBC\-4
-revision 11 while the others are in the SBC\-3 standard.
+revision 11 while the others are in the SBC\-3 standard.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
The options are arranged in alphabetical order based on the long
@@ -536,6 +536,10 @@ would be 520 bytes. To send the 32 byte variant add \-\-32 as in:
sg_write_x \-\-atomic=0 \-\-32 \-\-bs=512 \-\-in=/dev/zero \-\-lba=0x1234
\-\-num=4 /dev/sdc
.PP
+For examples using 'sg_write_x \-\-same=NDOB' see the manpage for
+sg_write_same(8). The syntax is a little different but the semantics are the
+same.
+.PP
To send a WRITE STREAM(32) with a STR_ID of 1 use the following:
.PP
sg_write_x \-\-stream=1 \-\-32 \-\-bs=512 \-\-in=/dev/zero \-\-lba=0x1234
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 78ab59d6..09ccd98b 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Wed May 13 2020 - dgilbert at interlog dot com
+* Mon Jun 01 2020 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.46
diff --git a/src/Makefile.am b/src/Makefile.am
index 2c423d9d..c6581efa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,9 +4,9 @@ bin_PROGRAMS = \
sg_get_config sg_get_elem_status sg_get_lba_status sg_ident sg_inq \
sg_logs sg_luns sg_modes sg_opcodes sg_persist sg_prevent sg_raw \
sg_rdac sg_read_attr sg_read_block_limits sg_read_buffer \
- sg_read_long sg_readcap sg_reassign sg_referrals sg_rep_zones \
- sg_requests sg_reset_wp sg_rmsn sg_rtpg sg_safte sg_sanitize \
- sg_sat_identify sg_sat_phy_event sg_sat_read_gplog \
+ sg_read_long sg_readcap sg_reassign sg_referrals sg_rep_pip \
+ sg_rep_zones sg_requests sg_reset_wp sg_rmsn sg_rtpg sg_safte \
+ sg_sanitize sg_sat_identify sg_sat_phy_event sg_sat_read_gplog \
sg_sat_set_features sg_seek sg_senddiag sg_ses sg_ses_microcode \
sg_start sg_stpg sg_stream_ctl sg_sync sg_timestamp sg_turs sg_unmap \
sg_verify sg_vpd sg_wr_mode sg_write_buffer sg_write_long \
@@ -129,6 +129,8 @@ sg_requests_LDADD = ../lib/libsgutils2.la
sg_referrals_LDADD = ../lib/libsgutils2.la
+sg_rep_pip_LDADD = ../lib/libsgutils2.la
+
sg_rep_zones_LDADD = ../lib/libsgutils2.la
sg_reset_wp_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index d72d77f7..2ec6a12b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -97,9 +97,10 @@ bin_PROGRAMS = sg_bg_ctl$(EXEEXT) sg_compare_and_write$(EXEEXT) \
sg_raw$(EXEEXT) sg_rdac$(EXEEXT) sg_read_attr$(EXEEXT) \
sg_read_block_limits$(EXEEXT) sg_read_buffer$(EXEEXT) \
sg_read_long$(EXEEXT) sg_readcap$(EXEEXT) sg_reassign$(EXEEXT) \
- sg_referrals$(EXEEXT) sg_rep_zones$(EXEEXT) \
- sg_requests$(EXEEXT) sg_reset_wp$(EXEEXT) sg_rmsn$(EXEEXT) \
- sg_rtpg$(EXEEXT) sg_safte$(EXEEXT) sg_sanitize$(EXEEXT) \
+ sg_referrals$(EXEEXT) sg_rep_pip$(EXEEXT) \
+ sg_rep_zones$(EXEEXT) sg_requests$(EXEEXT) \
+ sg_reset_wp$(EXEEXT) sg_rmsn$(EXEEXT) sg_rtpg$(EXEEXT) \
+ sg_safte$(EXEEXT) sg_sanitize$(EXEEXT) \
sg_sat_identify$(EXEEXT) sg_sat_phy_event$(EXEEXT) \
sg_sat_read_gplog$(EXEEXT) sg_sat_set_features$(EXEEXT) \
sg_seek$(EXEEXT) sg_senddiag$(EXEEXT) sg_ses$(EXEEXT) \
@@ -237,6 +238,9 @@ sg_reassign_DEPENDENCIES = ../lib/libsgutils2.la
sg_referrals_SOURCES = sg_referrals.c
sg_referrals_OBJECTS = sg_referrals.$(OBJEXT)
sg_referrals_DEPENDENCIES = ../lib/libsgutils2.la
+sg_rep_pip_SOURCES = sg_rep_pip.c
+sg_rep_pip_OBJECTS = sg_rep_pip.$(OBJEXT)
+sg_rep_pip_DEPENDENCIES = ../lib/libsgutils2.la
sg_rep_zones_SOURCES = sg_rep_zones.c
sg_rep_zones_OBJECTS = sg_rep_zones.$(OBJEXT)
sg_rep_zones_DEPENDENCIES = ../lib/libsgutils2.la
@@ -389,12 +393,12 @@ am__depfiles_remade = ./$(DEPDIR)/sg_bg_ctl.Po \
./$(DEPDIR)/sg_read_block_limits.Po \
./$(DEPDIR)/sg_read_buffer.Po ./$(DEPDIR)/sg_read_long.Po \
./$(DEPDIR)/sg_readcap.Po ./$(DEPDIR)/sg_reassign.Po \
- ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rep_zones.Po \
- ./$(DEPDIR)/sg_requests.Po ./$(DEPDIR)/sg_reset.Po \
- ./$(DEPDIR)/sg_reset_wp.Po ./$(DEPDIR)/sg_rmsn.Po \
- ./$(DEPDIR)/sg_rtpg.Po ./$(DEPDIR)/sg_safte.Po \
- ./$(DEPDIR)/sg_sanitize.Po ./$(DEPDIR)/sg_sat_identify.Po \
- ./$(DEPDIR)/sg_sat_phy_event.Po \
+ ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rep_pip.Po \
+ ./$(DEPDIR)/sg_rep_zones.Po ./$(DEPDIR)/sg_requests.Po \
+ ./$(DEPDIR)/sg_reset.Po ./$(DEPDIR)/sg_reset_wp.Po \
+ ./$(DEPDIR)/sg_rmsn.Po ./$(DEPDIR)/sg_rtpg.Po \
+ ./$(DEPDIR)/sg_safte.Po ./$(DEPDIR)/sg_sanitize.Po \
+ ./$(DEPDIR)/sg_sat_identify.Po ./$(DEPDIR)/sg_sat_phy_event.Po \
./$(DEPDIR)/sg_sat_read_gplog.Po \
./$(DEPDIR)/sg_sat_set_features.Po \
./$(DEPDIR)/sg_scan_linux.Po ./$(DEPDIR)/sg_scan_win32.Po \
@@ -437,14 +441,14 @@ SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c sg_dd.c \
sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \
sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \
sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \
- sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_zones.c \
- sg_requests.c sg_reset.c sg_reset_wp.c sg_rmsn.c sg_rtpg.c \
- sg_safte.c sg_sanitize.c sg_sat_identify.c sg_sat_phy_event.c \
- sg_sat_read_gplog.c sg_sat_set_features.c $(sg_scan_SOURCES) \
- sg_seek.c sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c \
- sg_stpg.c sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c \
- sg_timestamp.c sg_turs.c sg_unmap.c sg_verify.c \
- $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
+ sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_pip.c \
+ sg_rep_zones.c sg_requests.c sg_reset.c sg_reset_wp.c \
+ sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c sg_sat_identify.c \
+ sg_sat_phy_event.c sg_sat_read_gplog.c sg_sat_set_features.c \
+ $(sg_scan_SOURCES) sg_seek.c sg_senddiag.c sg_ses.c \
+ sg_ses_microcode.c sg_start.c sg_stpg.c sg_stream_ctl.c \
+ sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
+ sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \
sg_xcopy.c sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
@@ -454,10 +458,10 @@ DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \
sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \
sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \
- sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_zones.c \
- sg_requests.c sg_reset.c sg_reset_wp.c sg_rmsn.c sg_rtpg.c \
- sg_safte.c sg_sanitize.c sg_sat_identify.c sg_sat_phy_event.c \
- sg_sat_read_gplog.c sg_sat_set_features.c \
+ sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_pip.c \
+ sg_rep_zones.c sg_requests.c sg_reset.c sg_reset_wp.c \
+ sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c sg_sat_identify.c \
+ sg_sat_phy_event.c sg_sat_read_gplog.c sg_sat_set_features.c \
$(am__sg_scan_SOURCES_DIST) sg_seek.c sg_senddiag.c sg_ses.c \
sg_ses_microcode.c sg_start.c sg_stpg.c sg_stream_ctl.c \
sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
@@ -665,6 +669,7 @@ sg_read_long_LDADD = ../lib/libsgutils2.la
sg_reassign_LDADD = ../lib/libsgutils2.la
sg_requests_LDADD = ../lib/libsgutils2.la
sg_referrals_LDADD = ../lib/libsgutils2.la
+sg_rep_pip_LDADD = ../lib/libsgutils2.la
sg_rep_zones_LDADD = ../lib/libsgutils2.la
sg_reset_wp_LDADD = ../lib/libsgutils2.la
sg_rmsn_LDADD = ../lib/libsgutils2.la
@@ -908,6 +913,10 @@ sg_referrals$(EXEEXT): $(sg_referrals_OBJECTS) $(sg_referrals_DEPENDENCIES) $(EX
@rm -f sg_referrals$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_referrals_OBJECTS) $(sg_referrals_LDADD) $(LIBS)
+sg_rep_pip$(EXEEXT): $(sg_rep_pip_OBJECTS) $(sg_rep_pip_DEPENDENCIES) $(EXTRA_sg_rep_pip_DEPENDENCIES)
+ @rm -f sg_rep_pip$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sg_rep_pip_OBJECTS) $(sg_rep_pip_LDADD) $(LIBS)
+
sg_rep_zones$(EXEEXT): $(sg_rep_zones_OBJECTS) $(sg_rep_zones_DEPENDENCIES) $(EXTRA_sg_rep_zones_DEPENDENCIES)
@rm -f sg_rep_zones$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_rep_zones_OBJECTS) $(sg_rep_zones_LDADD) $(LIBS)
@@ -1098,6 +1107,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_readcap.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_reassign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_referrals.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_pip.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_zones.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_requests.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_reset.Po@am__quote@ # am--include-marker
@@ -1331,6 +1341,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/sg_readcap.Po
-rm -f ./$(DEPDIR)/sg_reassign.Po
-rm -f ./$(DEPDIR)/sg_referrals.Po
+ -rm -f ./$(DEPDIR)/sg_rep_pip.Po
-rm -f ./$(DEPDIR)/sg_rep_zones.Po
-rm -f ./$(DEPDIR)/sg_requests.Po
-rm -f ./$(DEPDIR)/sg_reset.Po
@@ -1448,6 +1459,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/sg_readcap.Po
-rm -f ./$(DEPDIR)/sg_reassign.Po
-rm -f ./$(DEPDIR)/sg_referrals.Po
+ -rm -f ./$(DEPDIR)/sg_rep_pip.Po
-rm -f ./$(DEPDIR)/sg_rep_zones.Po
-rm -f ./$(DEPDIR)/sg_requests.Po
-rm -f ./$(DEPDIR)/sg_reset.Po
diff --git a/src/sg_rep_pip.c b/src/sg_rep_pip.c
new file mode 100644
index 00000000..56d12e53
--- /dev/null
+++ b/src/sg_rep_pip.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2014-2020 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.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <getopt.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sg_lib.h"
+#include "sg_lib_data.h"
+#include "sg_pt.h"
+#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
+#include "sg_pr2serr.h"
+
+/* A utility program originally written for the Linux OS SCSI subsystem.
+ *
+ *
+ * This program issues the SCSI REPORT PROVISIONING INITIALIZATION PATTERN
+ * command to the given SCSI device and outputs the response. Based on
+ * sbc4r21.pdf
+ */
+
+static const char * version_str = "1.01 20200605";
+
+#define MAX_RPIP_BUFF_LEN (1024 * 1024)
+#define DEF_RPIP_BUFF_LEN 512
+
+#define SG_MAINT_IN_CMDLEN 12
+
+#define REPORT_PROVISIONING_INITIALIZATION_PATTERN_SA 0x1d
+
+#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
+#define DEF_PT_TIMEOUT 60 /* 60 seconds */
+
+static const char * rpip_s = "Report provisioning initialization pattern";
+
+
+static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
+ {"maxlen", required_argument, 0, 'm'},
+ {"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'R'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+
+static void
+usage(void)
+{
+ pr2serr("Usage: "
+ "sg_rep_pip [--help] [--hex] [--maxlen=LEN] [--raw] "
+ "[--readonly]\n"
+ " [--verbose] [--version] DEVICE\n");
+ pr2serr(" where:\n"
+ " --help|-h prints out this usage message\n"
+ " --hex|-H output response in hexadecimal "
+ "(default); used\n"
+ " twice: hex without addresses at start "
+ "of line\n"
+ " --maxlen=LEN|-m LEN max response length (allocation "
+ "length in cdb)\n"
+ " (def: 512 bytes)\n"
+ " --raw|-r output response in binary\n"
+ " --readonly|-R open DEVICE read-only (def: read-write)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string and exit\n\n"
+ "Sends a SCSI REPORT PROVISIONING INITIALIZATION PATTERN "
+ "command and outputs\nthe response in ASCII hexadecimal or "
+ "binary.\n");
+}
+
+/* Invokes a SCSI REPORT PROVISIONING INITIALIZATION PATTERN command (SBC).
+ * Return of 0 -> success, various SG_LIB_CAT_* positive values or
+ * -1 -> other errors */
+static int
+sg_ll_report_pip(int sg_fd, void * resp, int mx_resp_len, int * residp,
+ bool noisy, int verbose)
+{
+ int ret, res, sense_cat;
+ uint8_t rz_cdb[SG_MAINT_IN_CMDLEN] =
+ {SG_MAINTENANCE_IN, REPORT_PROVISIONING_INITIALIZATION_PATTERN_SA,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rz_cdb + 6);
+ if (verbose) {
+ char b[128];
+
+ pr2serr(" %s cdb: %s\n", rpip_s,
+ sg_get_command_str(rz_cdb, SG_MAINT_IN_CMDLEN, false,
+ sizeof(b), b));
+ }
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, rz_cdb, sizeof(rz_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, rpip_s, res, noisy, verbose, &sense_cat);
+ if (-1 == ret)
+ ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else
+ ret = 0;
+ if (residp)
+ *residp = get_scsi_pt_resid(ptvp);
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+static void
+dStrRaw(const uint8_t * str, int len)
+{
+ int k;
+
+ for (k = 0; k < len; ++k)
+ printf("%c", str[k]);
+}
+
+
+int
+main(int argc, char * argv[])
+{
+ bool do_raw = false;
+ bool o_readonly = false;
+ bool verbose_given = false;
+ bool version_given = false;
+ int res, c, resid, rlen;
+ int sg_fd = -1;
+ int do_help = 0;
+ int do_hex = 1;
+ int maxlen = 0;
+ int ret = 0;
+ int verbose = 0;
+ const char * device_name = NULL;
+ uint8_t * rpipBuff = NULL;
+ uint8_t * free_rpip = NULL;
+ char b[80];
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hHm:rRvV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ ++do_help;
+ break;
+ case 'H':
+ ++do_hex;
+ break;
+ case 'm':
+ maxlen = sg_get_num(optarg);
+ if ((maxlen < 0) || (maxlen > MAX_RPIP_BUFF_LEN)) {
+ pr2serr("argument to '--maxlen' should be %d or less\n",
+ MAX_RPIP_BUFF_LEN);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
+ case 'r':
+ do_raw = true;
+ break;
+ case 'R':
+ o_readonly = true;
+ break;
+ case 'v':
+ verbose_given = true;
+ ++verbose;
+ break;
+ case 'V':
+ version_given = true;
+ break;
+ default:
+ pr2serr("unrecognised option code 0x%x ??\n", c);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (optind < argc) {
+ if (NULL == device_name) {
+ device_name = argv[optind];
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ pr2serr("Unexpected extra argument: %s\n", argv[optind]);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+#ifdef DEBUG
+ pr2serr("In DEBUG mode, ");
+ if (verbose_given && version_given) {
+ pr2serr("but override: '-vV' given, zero verbose and continue\n");
+ verbose_given = false;
+ version_given = false;
+ verbose = 0;
+ } else if (! verbose_given) {
+ pr2serr("set '-vv'\n");
+ verbose = 2;
+ } else
+ pr2serr("keep verbose=%d\n", verbose);
+#else
+ if (verbose_given && version_given)
+ pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
+#endif
+ if (version_given) {
+ pr2serr("version: %s\n", version_str);
+ return 0;
+ }
+
+ if (do_help) {
+ usage();
+ return 0;
+ }
+ if (NULL == device_name) {
+ pr2serr("missing device name!\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+
+ if (do_raw) {
+ if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
+ perror("sg_set_binary_mode");
+ return SG_LIB_FILE_ERROR;
+ }
+ }
+
+ sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
+ if (sg_fd < 0) {
+ if (verbose)
+ pr2serr("open error: %s: %s\n", device_name,
+ safe_strerror(-sg_fd));
+ ret = sg_convert_errno(-sg_fd);
+ goto the_end;
+ }
+
+ if (0 == maxlen)
+ maxlen = DEF_RPIP_BUFF_LEN;
+ rpipBuff = (uint8_t *)sg_memalign(maxlen, 0, &free_rpip, verbose > 3);
+ if (NULL == rpipBuff) {
+ pr2serr("unable to sg_memalign %d bytes\n", maxlen);
+ return sg_convert_errno(ENOMEM);
+ }
+ res = sg_ll_report_pip(sg_fd, rpipBuff, maxlen, &resid, true, verbose);
+ ret = res;
+ if (0 == res) {
+ rlen = maxlen - resid;
+ if (rlen < 4) {
+ pr2serr("Response length (%d) too short\n", rlen);
+ ret = SG_LIB_CAT_MALFORMED;
+ goto the_end;
+ }
+ if (do_raw) {
+ dStrRaw(rpipBuff, rlen);
+ goto the_end;
+ }
+ if (do_hex && (2 != do_hex)) {
+ hex2stdout(rpipBuff, rlen, ((1 == do_hex) ? 1 : -1));
+ goto the_end;
+ }
+ } else if (SG_LIB_CAT_INVALID_OP == res)
+ pr2serr("%s command not supported\n", rpip_s);
+ else {
+ sg_get_category_sense_str(res, sizeof(b), b, verbose);
+ pr2serr("%s command: %s\n", rpip_s, b);
+ }
+
+the_end:
+ if (free_rpip)
+ free(free_rpip);
+ if (sg_fd >= 0) {
+ res = sg_cmds_close_device(sg_fd);
+ if (res < 0) {
+ pr2serr("close error: %s\n", safe_strerror(-res));
+ if (0 == ret)
+ ret = sg_convert_errno(-res);
+ }
+ }
+ if (0 == verbose) {
+ if (! sg_if_can2stderr("sg_rep_pip failed: ", ret))
+ pr2serr("Some error occurred, try again with '-v' "
+ "or '-vv' for more information\n");
+ }
+ return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+}
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index 985a9677..160fcd83 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2019 D. Gilbert
+ * Copyright (C) 2018-2020 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)
@@ -60,7 +60,7 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.14 20191116";
+static const char * version_str = "Version: 1.17 20200602";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
@@ -97,6 +97,8 @@ static bool show_size_value = false;
static bool do_v3_only = false;
static int childs_pid = 0;
+static int iterator_test = -1;
+static int object_walk_test = -1;
static int sg_drv_ver_num = 0;
static int q_len = DEF_Q_LEN;
static int sleep_secs = 0;
@@ -112,15 +114,21 @@ static char * file_name = NULL;
static void
usage(void)
{
- printf("Usage: sg_tst_ioctl [-3] [-c] [-f] [-h] [-l=Q_LEN] "
- "[-m=MRQS[,I|S]]\n"
- " [-M] [-n] [-o] [-r=SZ] [-s=SEC] [-S] [-t] "
- "[-T=NUM]\n"
- " [-v] [-V] [-w] <sg_device> [<sg_device2>]\n"
+ printf("Usage: sg_tst_ioctl [-3] [-c] [-f] [-h] [-I=0|1] [-J=0|1] "
+ "[-l=Q_LEN]\n"
+ " [-m=MRQS[,I|S]] [-M] [-n] [-o] [-r=SZ] "
+ "[-s=SEC]\n"
+ " [-S] [-t] [-T=NUM] [-v] [-V] [-w]\n"
+ " <sg_device> [<sg_device2>]\n"
" where:\n"
" -c timestamp when sg driver created <sg_device>\n"
" -f fork and test share between processes\n"
" -h help: print usage message then exit\n"
+ " -I=0|1 iterator test of mid-level; 0: unlocked, 1: "
+ "locked\n"
+ " does test -T=NUM times, outputs duration\n"
+ " -J=0|1 object walk (to root); 0: without ptr; 1: with "
+ "ptr\n"
" -l=Q_LEN queue length, between 1 and 511 (def: 16)\n"
" -m=MRQS[,I|S] test multi-req, MRQS number to do; if "
"the letter\n"
@@ -781,6 +789,20 @@ main(int argc, char * argv[])
else if (0 == memcmp("-h", argv[k], 2)) {
file_name = 0;
break;
+ } else if (0 == memcmp("-I=", argv[k], 3)) {
+ iterator_test = atoi(argv[k] + 3);
+ if ((iterator_test > 1) || (iterator_test < -1)) {
+ printf("Expect -I= to take a number, either 0 or 1\n");
+ file_name = 0;
+ break;
+ }
+ } else if (0 == memcmp("-J=", argv[k], 3)) {
+ object_walk_test = atoi(argv[k] + 3);
+ if ((object_walk_test > 1) || (object_walk_test < -1)) {
+ printf("Expect -J= to take a number, either 0 or 1\n");
+ file_name = 0;
+ break;
+ }
} else if (0 == memcmp("-l=", argv[k], 3)) {
q_len = atoi(argv[k] + 3);
if ((q_len > 511) || (q_len < 1)) {
@@ -878,6 +900,9 @@ main(int argc, char * argv[])
break;
}
}
+ if (iterator_test >= 0)
+ nw_given = false;
+
if (show_size_value) {
struct utsname unam;
@@ -947,26 +972,82 @@ main(int argc, char * argv[])
}
printf("Linux sg driver version: %d\n", sg_drv_ver_num);
+ if (object_walk_test >= 0) {
+ k = (object_walk_test == 0) ? -999 : 999;
+ if (ioctl(sg_fd, SG_SET_DEBUG, &k) < 0) {
+ res = errno;
+ fprintf(stderr, "%s%d: ioctl(SG_SET_DEBUG) failed errno=%d\n",
+ relative_cp, k, res);
+ }
+ goto out;
+ }
+
if (create_time && (sg_drv_ver_num > 40030)) {
pr_create_dev_time(sg_fd, file_name);
goto out;
}
- if (nw_given) { /* time ioctl(SG_GET_NUM_WAITING) */
+ if (nw_given || (iterator_test >= 0)) { /* -T=NUM and/or -I=0|1 */
+ /* time ioctl(SG_GET_NUM_WAITING) or do iterator_test */
int nw, sum_nw;
struct timespec start_tm, fin_tm, res_tm;
- printf("Timing %d calls to ioctl(SG_GET_NUM_WAITING)\n", num_sgnw);
+ if (nw_given)
+ printf("Timing %d calls to ioctl(SG_GET_NUM_WAITING)\n",
+ num_sgnw);
+ else
+ printf("Timing calls to ioctl(SG_SET_DEBUG, %d)\n",
+ num_sgnw);
if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
res = errno;
perror("start clock_gettime() failed:");
goto out;
}
- for (k = 0, sum_nw = 0; k < num_sgnw; ++k, sum_nw += nw) {
- if (ioctl(sg_fd, SG_GET_NUM_WAITING, &nw) < 0) {
+ if (nw_given) {
+ for (k = 0, sum_nw = 0; k < num_sgnw; ++k, sum_nw += nw) {
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &nw) < 0) {
+ res = errno;
+ fprintf(stderr, "%d: ioctl(SG_GET_NUM_WAITING) failed "
+ "errno=%d\n", k, res);
+ goto out;
+ }
+ }
+ } else {
+ int fd, pid;
+
+ k = num_sgnw + 1000;
+ if (0 == iterator_test)
+ k = -k;
+ if (second_fname) {
+ if ((sg_fd2 = open(second_fname, O_RDWR)) < 0) {
+ snprintf(ebuff, EBUFF_SZ,
+ "%s: error opening file: %s", __func__, second_fname);
+ perror(ebuff);
+ return 1;
+ }
+ printf("About to fork due to second filename\n");
+ pid = fork();
+ if (pid < 0) {
+ perror("fork() failed");
+ goto out;
+ } else if (0 == pid) {
+ relative_cp = "child: ";
+ is_parent = false;
+ fd = sg_fd2;
+ } else {
+ relative_cp = "parent: ";
+ is_parent = true;
+ childs_pid = pid;
+ fd = sg_fd;
+ }
+ } else {
+ fd = sg_fd;
+ relative_cp = "";
+ }
+ if (ioctl(fd, SG_SET_DEBUG, &k) < 0) {
res = errno;
- fprintf(stderr, "%d: ioctl(SG_GET_NUM_WAITING) failed "
- "errno=%d\n", k, res);
+ fprintf(stderr, "%s%d: ioctl(SG_SET_DEBUG) failed errno=%d\n",
+ relative_cp, k, res);
goto out;
}
}
@@ -982,21 +1063,21 @@ main(int argc, char * argv[])
res_tm.tv_nsec += 1000000000;
}
if (verbose) {
- if (verbose > 1)
+ if (nw_given && (verbose > 1))
printf("sum of num_waiting_s=%d\n", sum_nw);
- printf("elapsed time (nanosecond precision): %d.%09d secs\n",
- (int)res_tm.tv_sec, (int)res_tm.tv_nsec);
+ printf("%selapsed time (nanosecond precision): %d.%09d secs\n",
+ relative_cp, (int)res_tm.tv_sec, (int)res_tm.tv_nsec);
} else
- printf("elapsed time: %d.%06d secs\n", (int)res_tm.tv_sec,
- (int)(res_tm.tv_nsec / 1000));
+ printf("%selapsed time: %d.%06d secs\n", relative_cp,
+ (int)res_tm.tv_sec, (int)(res_tm.tv_nsec / 1000));
if (num_sgnw >= 100) {
double m = (double)res_tm.tv_sec +
((double)res_tm.tv_nsec / 1000000000.0);
if (m > 0.000001)
- printf("Calls per second: %.2f\n", (double)num_sgnw / m);
+ printf("%sCalls per second: %.2f\n", relative_cp,
+ (double)num_sgnw / m);
}
-
res = 0;
goto out;
}
@@ -1191,7 +1272,8 @@ main(int argc, char * argv[])
}
out:
- close(sg_fd);
+ if (sg_fd >= 0)
+ close(sg_fd);
if (sg_fd2 >= 0)
close(sg_fd2);
return res;