aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2020-01-25 12:58:12 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2020-01-25 12:58:12 +0000
commite541eac9a0aa7a5e9eaa9d1c9e3c58d7605963b0 (patch)
tree6fe48e57ba62239b1f043fcee45bab93688da043
parent68c8a6cc83711259bd90e6296c63ee384d477b18 (diff)
downloadsg3_utils-e541eac9a0aa7a5e9eaa9d1c9e3c58d7605963b0.tar.gz
sbc4r18+spc6r01 partial catch-up; sg_format: add FORMAT WITH PRESET support
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@839 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--COVERAGE3
-rw-r--r--CREDITS5
-rw-r--r--ChangeLog7
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_dd.814
-rw-r--r--doc/sg_format.8165
-rw-r--r--doc/sg_luns.86
-rw-r--r--doc/sg_modes.86
-rw-r--r--doc/sg_readcap.817
-rw-r--r--doc/sg_sat_identify.86
-rw-r--r--doc/sg_write_x.86
-rw-r--r--include/sg_lib.h2
-rw-r--r--lib/sg_lib.c4
-rw-r--r--lib/sg_lib_data.c7
-rw-r--r--scripts/55-scsi-sg3_id.rules2
-rw-r--r--scripts/58-scsi-sg3_symlink.rules2
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_dd.c41
-rw-r--r--src/sg_format.c287
-rw-r--r--src/sg_inq.c6
-rw-r--r--src/sg_luns.c7
-rw-r--r--src/sg_modes.c19
-rw-r--r--src/sg_readcap.c12
-rw-r--r--src/sg_rep_zones.c8
-rw-r--r--src/sg_seek.c9
-rw-r--r--src/sg_vpd.c6
-rw-r--r--testing/sgh_dd.cpp164
27 files changed, 614 insertions, 201 deletions
diff --git a/COVERAGE b/COVERAGE
index 00ce453f..2d5a7e38 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -29,6 +29,7 @@ INQUIRY sg_dd, sg_format, sg_inq, sginfo,
FINISH ZONE sg_zone
FORMAT MEDIUM sg_format, ++ [SSC]
FORMAT UNIT sg_format, ++ [SBC]
+FORMAT WITH PRESET sg_format, ++ [SBC]
LOG SELECT sg_logs('-r' or '-select'), ++
LOG SENSE sg_logs, ++
MODE SELECT(6) sdparm, sg_wr_mode, sginfo, sg_format,
@@ -159,4 +160,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-28th August 2019
+24th January 2020
diff --git a/CREDITS b/CREDITS
index be90a425..e48eb446 100644
--- a/CREDITS
+++ b/CREDITS
@@ -145,6 +145,9 @@ Tom Steudten <steudten at gmx dot ch> sginfo addition: add '-Fhead' option
Trent Piepho <xyzzy at speakeasy dot org> print out some "sense key specific"
data and "-6" switch for sg_modes
+Xose Vazquez Perez <xose dot vazquez at gmail dot com>
+ documentation corrections [20200117]
+
Douglas Gilbert
-29th April 2019
+17th January 2020
diff --git a/ChangeLog b/ChangeLog
index 99151f83..9f7c257f 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 [20200111] [svn: r838]
+Changelog for sg3_utils-1.45 [20200125] [svn: r839]
- sg_get_elem_status: new utility [sbc4r16]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
@@ -18,6 +18,7 @@ Changelog for sg3_utils-1.45 [20200111] [svn: r838]
- sg_inq: update version descriptors to spc5r21
- add some NVMe 1.4 snippets to ctl identify
- sg_format: add --dcrt used twice (FOV=1 DCRT=0)
+ - add support for FORMAT WITH PRESET (sbc4r18)
- sg_raw: fix --send bug when using stdin
- sg_vpd: 3pc VPD page add copy group descriptor
- add --examine option
@@ -32,6 +33,7 @@ Changelog for sg3_utils-1.45 [20200111] [svn: r838]
- sg_scan (win32): expand limits for big arrays
- sg_modes: placeholders for Command duration limit
T2A and T2B mpages (sbc4r17)
+ - improve zbc support (e.g. caching mpage)
- sg_logs: add Command duration limits statistics
lpage (spc6r01)
- zoned block device statistics log page: shorten
@@ -41,12 +43,13 @@ Changelog for sg3_utils-1.45 [20200111] [svn: r838]
apart from page 0x0,0xff. Used three times:
list all pages and subpages names reported
- sg_reassign: for defect list format 6 (vendor
- specfic) don't try to decode
+ specific) don't try to decode
- sg_rep_zones: expand some fields per zbc2r04
- sg_verify: correct so issues VERIFY(16)
- add --0 and --ff options and implement
bytchk=3 properly
- sg_write_same: add --ff for 0xff fill
+ - sg_luns: report new "target commands" w-lun (19-117)
- sg_dd: add --verify support
- inhex directory: new, contains ASCII hex files
that can be used with the '--inhex=' option
diff --git a/debian/changelog b/debian/changelog
index ab35da37..eceefbe7 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> Wed, 01 Jan 2020 14:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Sat, 25 Jan 2020 08:00:00 -0500
sg3-utils (1.44-0.1) unstable; urgency=low
diff --git a/doc/sg_dd.8 b/doc/sg_dd.8
index d8fcd487..2c6caedc 100644
--- a/doc/sg_dd.8
+++ b/doc/sg_dd.8
@@ -1,4 +1,4 @@
-.TH SG_DD "8" "December 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_DD "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_dd \- copy data to and from files and devices, especially SCSI
devices
@@ -219,10 +219,12 @@ when used once, this is equivalent to \fIverbose=1\fR. When used
twice (e.g. "\-vv") this is equivalent to \fIverbose=2\fR, etc.
.TP
\fB\-x\fR, \fB\-\-verify\fR
-do a verify operation (like Unix command cmp(1)) rather than a copy.
-Cannot be used with "oflag=sparse". \fIof=OFILE\fR must be given and
-\fIOFILE\fR must be an sg device or a block device with "oflag=sgio"
-alsoe given.
+do a verify operation (like Unix command cmp(1)) rather than a copy. Cannot
+be used with "oflag=sparse". \fIof=OFILE\fR must be given and \fIOFILE\fR
+must be an sg device or a block device with "oflag=sgio" also given. Uses the
+SCSI VERIFY command with the BYTCHK field set to 1. The VERIFY command is
+used instead of WRITE when this option is given. There is no VERIFY(6)
+command.
.TP
\fB\-V\fR, \fB\-\-version\fR
outputs version number information and exits.
@@ -507,7 +509,7 @@ Written by Douglas Gilbert and Peter Allworth.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2000\-2019 Douglas Gilbert
+Copyright \(co 2000\-2020 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_format.8 b/doc/sg_format.8
index c1b4f9d9..84ae8f54 100644
--- a/doc/sg_format.8
+++ b/doc/sg_format.8
@@ -1,17 +1,17 @@
-.TH SG_FORMAT "8" "January 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_FORMAT "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
-sg_format \- format, resize a SCSI disk or format a tape
+sg_format \- format, format with preset, resize SCSI disk; format tape
.SH SYNOPSIS
.B sg_format
[\fI\-\-cmplst=\fR{0|1}] [\fI\-\-count=COUNT\fR] [\fI\-\-dcrt\fR]
[\fI\-\-dry\-run\fR] [\fI\-\-early\fR] [\fI\-\-ffmt=FFMT\fR]
-[\fI\-\-fmtpinfo=FPI\fR] [\fI\-\-format\fR] [\fI\-\-help\fR]
-[\fI\-\-ip\-def\fR] [\fI\-\-long\fR] [\fI\-\-mode=MP\fR] [\fI\-\-pfu=PFU\fR]
-[\fI\-\-pie=PIE\fR] [\fI\-\-pinfo\fR] [\fI\-\-poll=PT\fR] [\fI\-\-quick\fR]
-[\fI\-\-resize\fR] [\fI\-\-rto_req\fR] [\fI\-\-security\fR] [\fI\-\-six\fR]
-[\fI\-\-size=LB_SZ\fR] [\fI\-\-tape=FM\fR] [\fI\-\-timeout=SECS\fR]
-[\fI\-\-verbose\fR] [\fI\-\-verify\fR] [\fI\-\-version\fR] [\fI\-\-wait\fR]
-\fIDEVICE\fR
+[\fI\-\-fmtmaxlba\R] [\fI\-\-fmtpinfo=FPI\fR] [\fI\-\-format\fR]
+[\fI\-\-help\fR] [\fI\-\-ip\-def\fR] [\fI\-\-long\fR] [\fI\-\-mode=MP\fR]
+[\fI\-\-pfu=PFU\fR] [\fI\-\-pie=PIE\fR] [\fI\-\-pinfo\fR] [\fI\-\-poll=PT\fR]
+[\fI\-\-preset=ID\fR] [\fI\-\-quick\fR] [\fI\-\-resize\fR] [\fI\-\-rto_req\fR]
+[\fI\-\-security\fR] [\fI\-\-six\fR] [\fI\-\-size=LB_SZ\fR]
+[\fI\-\-tape=FM\fR] [\fI\-\-timeout=SECS\fR] [\fI\-\-verbose\fR]
+[\fI\-\-verify\fR] [\fI\-\-version\fR] [\fI\-\-wait\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -24,6 +24,12 @@ recommendation typically leaves aside a certain number of tracks, spread
across the media, for reassignment of blocks to logical block addresses
during the life of the disk.
.PP
+This utility issues one of three SCSI format commands: FORMAT UNIT, FORMAT
+MEDIUM or FORMAT WITH PRESET. In the following description, unqualified
+sections will usually be referring to the SCSI FORMAT UNIT command. Both
+FORMAT UNIT and FORMAT WITH PRESET apply to disks (or disk\-like devices).
+The FORMAT MEDIUM command is for tapes.
+.PP
This utility can format modern SCSI disks and potentially change their block
size (if permitted) and the block count (i.e. number of accessible blocks on
the media also known as "resizing"). Resizing a disk to less than the
@@ -42,11 +48,12 @@ response to a MODE SENSE command and the response to a READ CAPACITY command.
The reason for this double check is to detect a "format corrupt" state (see
the NOTES section). This usage will not modify the disk.
.PP
-When this utility is used with the "\-\-format" (or "\-F") option it will
-attempt to format the given DEVICE. In the absence of the \fI\-\-quick\fR
-option there is a 15 second pause during which time the user is invited
-thrice (5 seconds apart) to abort sg_format. This occurs just prior the SCSI
-FORMAT UNIT command being issued. See the NOTES section for more information.
+When this utility is used with either \fI\-\-format\fR, \fI\-\-preset=ID\fR
+or \fI\-\-tape=FM\fR, it will attempt to format the given DEVICE. In the
+absence of the \fI\-\-quick\fR option there is a 15 second pause during which
+time the user is invited thrice (5 seconds apart) to abort sg_format. This
+occurs just prior the SCSI FORMAT UNIT, FORMAT WITH PRESET or FORMAT MEDIUM
+command being issued. See the NOTES section for more information.
.PP
Protection information (PI) is optional and is made up of one or more
protection intervals, each made up of 8 bytes associated with a logical
@@ -58,8 +65,13 @@ INFORMATION section below for more information.
.PP
When the \fI\-\-tape=FM\fR option is given then the SCSI FORMAT MEDIUM
command is sent to the \fIDEVICE\fR. FORMAT MEDIUM is defined in the SSC
-documents at T10 and prepares a volume for use. That may include
-partitioning the medium. See the section below on TAPE for more information.
+documents at T10 and prepares a volume for use. That may include partitioning
+the medium. See the section below on TAPE for more information.
+.PP
+The FORMAT WITH PRESET was added in draft SBC\-4 revision 18. A preset
+pattern, selected by the PRESET IDENTIFIER field (\fI\-\-id=FWPID\fR),
+is written to the disk. See the FORMAT PRESETS VPD page (0xb8) for a list
+of available Format preset identifiers and their associated data.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
The options are arranged in alphabetical order based on the long
@@ -126,9 +138,10 @@ list associated with the FORMAT UNIT cdb.
.TP
\fB\-d\fR, \fB\-\-dry\-run\fR
this option will parse the command line, do all the preparation but bypass
-the actual FORMAT UNIT or FORMAT MEDIUM commands. Also if the options would
-cause the logical block size to change, then the MODE SELECT command that
-would do that is also bypassed when the dry run option is given.
+the actual FORMAT UNIT, FORMAT WITH PRESET or FORMAT MEDIUM command. Also if
+the options would otherwise cause the logical block size to change, then the
+MODE SELECT command that would do that is also bypassed when the dry
+run option is given.
.TP
\fB\-e\fR, \fB\-\-early\fR
during a format operation, The default action of this utility is to poll the
@@ -158,6 +171,11 @@ without error. When \fIFFMT\fR is 2 the read operation may yield check
condition status with a sense key set to hardware error, medium error or
command aborted. See draft SBC\-4 revision 16 section 4.34 for more details.
.TP
+\fB\-b\fR, \fB\-\-fmtmaxlba\fR
+This option is only active if it is given together with the
+\fI\-\-preset=ID\fR option. If so it sets the FMTMAXLBA field in the FORMAT
+WITH PRESET command.
+.TP
\fB\-f\fR, \fB\-\-fmtpinfo\fR=\fIFPI\fR
sets the FMTPINFO field in the FORMAT UNIT cdb to a value between 0 and 3.
The default value is 0. The FMTPINFO field from SBC\-3 revision 16 is a 2
@@ -169,8 +187,10 @@ option should be used in their place. See the PROTECTION INFORMATION section
below for more information.
.TP
\fB\-F\fR, \fB\-\-format\fR
-issue a SCSI FORMAT UNIT command.
-.B This will destroy all the data held on the media.
+issue one of the three SCSI "format" commands. In the absence of the
+\fI\-\-preset=ID\fR and \fI\-\-tape=FM\fR options, the SCSI FORMAT UNIT
+command is issued.
+.B These commands will destroy all the data held on the media.
This option is required to change the block size of a disk. In the absence
of the \fI\-\-quick\fR option, the user is given a 15 second count down to
ponder the wisdom of doing this, during which time control\-C (amongst other
@@ -246,6 +266,12 @@ READY command is used, otherwise a REQUEST SENSE command is used. The
default is currently 0 but this will change to 1 in the near future. See
the NOTES sections below.
.TP
+\fB\-E\fR, \fB\-\-preset\fR=\fIID\fR
+this option instructs this utility to issue a SCSI FORMAT WITH PRESET
+command. The PRESET IDENTIFIER field in that cdb is set to \fIID\fR. The
+IMMED field in that cdb is also set unless the \fI\-\-wait\fR option is
+also given, in which case it is cleared.
+.TP
\fB\-Q\fR, \fB\-\-quick\fR
the default action (i.e. when the option is not given) is to give the user
15 seconds to reconsider doing a format operation on the \fIDEVICE\fR.
@@ -302,18 +328,18 @@ in a tape drive for use. Values for \fIFM\fR include 0 to do the "default"
format; 1 to partition a volume and 2 to do a default format then partition.
.TP
\fB\-m\fR, \fB\-\-timeout\fR=\fISECS\fR
-where \fISECS\fR is the FORMAT UNIT or FORMAT MEDIUM command timeout in
-seconds. \fISECS\fR will only be used if it exceeds the internal timeout
-which is 20 seconds if the IMMED bit is set and 72000 seconds (20 hours)
-or higher if the IMMED bit is not set. If the disk size exceeds 4 TB then
-the timeout value is increased to 144000 seconds (40 hours). And if it is
-greater than 8 TB then the timeout value is increased to 288000 seconds (80
-hours). If the timeout is exceeded then the operating system will typically
-abort the command. Aborting a command may escalate to a LUN reset (or
-worse). A timeout may also leave the disk or tape format operation
-incomplete. And that may result in the disk or tape being in a "format
-corrupt" state requiring another format to remedy the situation. So for
-various reasons timeouts are best avoided.
+where \fISECS\fR is the FORMAT UNIT, FORMAT WITH PRESET or FORMAT MEDIUM
+command timeout in seconds. \fISECS\fR will only be used if it exceeds the
+internal timeout which is 20 seconds if the IMMED bit is set and 72000
+seconds (20 hours) or higher if the IMMED bit is not set. If the disk size
+exceeds 4 TB then the timeout value is increased to 144000 seconds (40 hours).
+And if it is greater than 8 TB then the timeout value is increased to
+288000 seconds (80 hours). If the timeout is exceeded then the operating
+system will typically abort the command. Aborting a command may escalate to
+a LUN reset (or worse). A timeout may also leave the disk or tape format
+operation incomplete. And that may result in the disk or tape being in
+a "format corrupt" state requiring another format to remedy the situation.
+So for various reasons command timeouts are best avoided.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output). "\-vvv" gives
@@ -330,9 +356,9 @@ print the version string and then exit.
the default format action is to set the "IMMED" bit in the FORMAT UNIT
command's (short) parameter header. If this option (i.e. \fI\-\-wait\fR) is
given then the "IMMED" bit is not set. If \fI\-\-wait\fR is given then the
-FORMAT UNIT or FORMAT MEDIUM command waits until the format operation
-completes before returning its response. This can be many hours on large
-disks. See the \fI\-\-timeout=SECS\fR option.
+FORMAT UNIT, FORMAT WITH PRESET or FORMAT MEDIUM command waits until the
+format operation completes before returning its response. This can be many
+hours on large disks. See the \fI\-\-timeout=SECS\fR option.
.br
Alternatively this option may be useful when used together with
\fI\-\-ffmt=FFMT\fR (and \fIFFMT\fR greater than 0) since the fast format
@@ -433,32 +459,35 @@ the current version of this utility defaults to using TEST UNIT READY
commands to poll the disk to find out the progress of the format. The
\fI\-\-poll=PT\fR option has been added to control this.
.PP
-When the \fI\-\-format\fR option is given without the \fI\-\-wait\fR option
-then the SCSI FORMAT UNIT command is issued with the IMMED bit set which
-causes the SCSI command to return after it has started the format operation.
-The \fI\-\-early\fR option will cause sg_format to exit at that point.
-Otherwise the \fIDEVICE\fR is polled every 60 seconds or every 10 seconds
-if \fIFFMT\fR is non\-zero. The poll is with TEST UNIT READY or REQUEST SENSE
-commands until one reports an "all clear" (i.e. the format operation has
-completed). Normally these polling commands will result in a progress
-indicator (expressed as a percentage) being output to the screen. If the user
-gets bored watching the progress report then sg_format process can be
-terminated (e.g. with control\-C) without affecting the format operation
-which continues. However a target or device reset (or a power cycle) will
-probably cause the device to become "format corrupt".
-.PP
-When the \fI\-\-format\fR (or \fI\-\-tape\fR) and \fI\-\-wait\fR options are
-both given then this utility may take a long time to return. In this case
-care should be taken not to send any other SCSI commands to the disk as it
-may not respond leaving those commands queued behind the active format
-command. This may cause a timeout in the OS driver (in a lot shorter period
-than 20 hours applicable to some format operations). This may result in the
-OS resetting the disk leaving the format operation incomplete. This may leave
-the disk in a "format corrupt" state requiring another format to remedy
-the situation. Modern SCSI devices should yield a "not ready" sense key
-with an additional sense indicating a format is in progress. With older
-devices the user should take precautions that nothing attempts to access
-a device while it is being formatted.
+When the \fI\-\-format\fR, \fI\-\-preset=ID\fR or \fI\-\-tape=FM\fR option
+is given without the \fI\-\-wait\fR option then the corresponding SCSI
+command is issued with the IMMED bit set which causes the SCSI command to
+return after it has started the format operation. The \fI\-\-early\fR option
+will cause sg_format to exit at that point. Otherwise the \fIDEVICE\fR is
+polled every 60 seconds or every 10 seconds if \fIFFMT\fR is non\-zero. The
+poll is with TEST UNIT READY or REQUEST SENSE commands until one reports
+an "all clear" (i.e. the format operation has completed). Normally these
+polling commands will result in a progress indicator (expressed as a
+percentage) being output to the screen. If the user gets bored watching the
+progress report then sg_format process can be terminated (e.g. with
+control\-C) without affecting the format operation which continues. However
+a target or device reset (or a power cycle) will probably cause the format
+to cease and the \fIDEVICE\fR to become "format corrupt".
+.PP
+When the \fI\-\-format\fR (\fI\-\-preset=ID\fR or \fI\-\-tape\fR) and
+\fI\-\-wait\fR options are both given then this utility may take a long time
+to return. In this case care should be taken not to send any other SCSI
+commands to the disk as it may not respond leaving those commands queued
+behind the active format command. This may cause a timeout in the OS
+driver (in a lot shorter period than 20 hours applicable to some format
+operations). This may result in the OS resetting the disk leaving the format
+operation incomplete. This may leave the disk in a "format corrupt" state
+requiring another format to remedy the situation. Modern SCSI devices should
+yield a "not ready" sense key with an additional sense indicating a format
+is in progress. With older devices the user should take precautions that
+nothing attempts to access a device while it is being formatted. Unmounting
+in mounted file systems on a \fIDEVICE\fR prior to calling this utility
+is strongly advised.
.PP
When the block size (i.e. the number of bytes in each block) is changed
on a disk two SCSI commands must be sent: a MODE SELECT to change the block
@@ -640,7 +669,15 @@ Now /dev/sdd should have 512 byte logical block size. And to switch it back:
# sg_format \-\-format \-\-ffmt=1 \-\-size=4096 /dev/sdd
.PP
Since fast formats can be very quick (a matter of seconds) using the
-\-\-wait option may be appropriate
+\-\-wait option may be appropriate.
+.PP
+And tu use Format with preset this invocation might be used:
+.PP
+ # sg_format \-\-preset=1 \-\-fmtmaxlba /dev/sdd
+.PP
+The FORMAT PRESETS VPD page (0xb8) should be consulted to check that Preset
+identifier 0x1 is there and has the expected format (i.e. "default host aware
+zoned block device model with 512 bytes of user data in each logical block").
.SH EXIT STATUS
The exit status of sg_format is 0 when it is successful. Otherwise see
the sg3_utils(8) man page. Unless the \fI\-\-wait\fR option is given, the
@@ -651,7 +688,7 @@ Written by Grant Grundler, James Bottomley and Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2005\-2019 Grant Grundler, James Bottomley and Douglas Gilbert
+Copyright \(co 2005\-2020 Grant Grundler, James Bottomley and Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_luns.8 b/doc/sg_luns.8
index f27ed6f6..82927726 100644
--- a/doc/sg_luns.8
+++ b/doc/sg_luns.8
@@ -1,4 +1,4 @@
-.TH SG_LUNS "8" "June 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_LUNS "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_luns \- send SCSI REPORT LUNS command or decode given LUN
.SH SYNOPSIS
@@ -20,7 +20,7 @@ should be a list of LUNs ("a LUN inventory") for the I_T nexus associated
with the \fIDEVICE\fR. Roughly speaking that is all LUNs that share the
target device that the REPORT LUNS command is sent through. This command
is defined in the SPC\-3 and SPC\-4 SCSI standards and its support is
-mandatory. The most recent draft if SPC\5 revision 9.
+mandatory. The most recent draft if SPC\-6 revision 1.
.PP
When the \fI\-\-test=ALUN\fR option is given (the second form in the
SYNOPSIS), then the \fIALUN\fR value is decoded as outlined in various
@@ -311,7 +311,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2018 Douglas Gilbert
+Copyright \(co 2004\-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.
diff --git a/doc/sg_modes.8 b/doc/sg_modes.8
index d5cadc51..d68bc409 100644
--- a/doc/sg_modes.8
+++ b/doc/sg_modes.8
@@ -1,4 +1,4 @@
-.TH SG_MODES "8" "April 2019" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_MODES "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_modes \- reads mode pages with SCSI MODE SENSE command
.SH SYNOPSIS
@@ -22,7 +22,7 @@ outputs the response. There is a 6 byte and 10 byte (cdb) variant of the
MODE SENSE command, this utility defaults to the 10 byte variant. The SPC\-4
standard (and SPC\-5 drafts) include a note stating that implementers should
migrate away from the SCSI MODE SELECT(6) and MODE SENSE(6) commands in
-favour of the 10 byte variants (e.g. MODE SENSE(10)).
+favour of the 10 byte variants (e.g. MODE SENSE(10)).
.PP
This utility decodes mode page headers and block descriptors but outputs
the contents of each mode page in hex. It also has no facility to change
@@ -301,7 +301,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2000\-201p Douglas Gilbert
+Copyright \(co 2000\-2020 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_readcap.8 b/doc/sg_readcap.8
index ffc8724b..fa2afd34 100644
--- a/doc/sg_readcap.8
+++ b/doc/sg_readcap.8
@@ -1,15 +1,17 @@
-.TH SG_READCAP "8" "May 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_READCAP "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_readcap \- send SCSI READ CAPACITY command
.SH SYNOPSIS
.B sg_readcap
[\fI\-\-16\fR] [\fI\-\-brief\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR]
[\fI\-\-lba=LBA\fR] [\fI\-\-long\fR] [\fI\-\-pmi\fR] [\fI\-\-raw\fR]
-[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-zbc\fR]
+\fIDEVICE\fR
.PP
.B sg_readcap
[\fI\-16\fR] [\fI\-b\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-lba=LBA\fR]
-[\fI\-pmi\fR] [\fI\-r\fR] [\fI\-R\fR] [\fI\-v\fR] [\fI\-V\fR] \fIDEVICE\fR
+[\fI\-pmi\fR] [\fI\-r\fR] [\fI\-R\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-z\fR]
+\fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -104,6 +106,10 @@ increase level of verbosity. Can be used multiple times.
.TP
\fB\-V\fR, \fB\-\-version\fR
outputs version string then exits.
+.TP
+\fB\-z\fR, \fB\-\-zbc\fR
+additionally prints out the extra ZBC field (RC_BASIS) in the READ CAPACITY
+response. Using the option implicitly sets the \fI\-\-16\fR option.
.SH NOTES
The response to READ CAPACITY(16) contains a LBPRZ bit in the SBC\-3
standard (ANSI INCITS 514\-2014). There was also a LBPRZ bit with the same
@@ -171,6 +177,9 @@ and '\-vvv' are also accepted yielding greater verbosity.
.TP
\fB\-V\fR
outputs version string then exits.
+.TP
+\fB\-R\fR
+Equivalent to \fI\-\-zbc\fR in the main description.
.SH ENVIRONMENT VARIABLES
Since sg3_utils version 1.23 the environment variable SG3_UTILS_OLD_OPTS
can be given. When it is present this utility will expect the older command
@@ -179,7 +188,7 @@ using \fI\-\-old\fR (or \fI\-O\fR) as the first command line option.
.SH AUTHORS
Written by Douglas Gilbert
.SH COPYRIGHT
-Copyright \(co 1999\-2018 Douglas Gilbert
+Copyright \(co 1999\-2020 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_sat_identify.8 b/doc/sg_sat_identify.8
index aee34674..e811614a 100644
--- a/doc/sg_sat_identify.8
+++ b/doc/sg_sat_identify.8
@@ -1,4 +1,4 @@
-.TH SG_SAT_IDENTIFY "8" "January 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SAT_IDENTIFY "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_sat_identify \- send ATA IDENTIFY DEVICE command via SCSI to ATA
Translation (SAT) layer
@@ -23,7 +23,7 @@ www.t10.org) defines two SCSI "ATA PASS\-THROUGH" commands: one using a 16
byte "cdb" and the other with a 12 byte cdb. This utility defaults to using
the 16 byte cdb variant. SAT\-4 revision 5 added a SCSI "ATA
PASS\-THROUGH(32)" command. SAT\-2 and SAT\-3 are now also standards: SAT\-2
-ANSI INCITS 465\-2010 and SAT\3 ANSI INCITS 517-2015 . The SAT\-4 project
+ANSI INCITS 465\-2010 and SAT\-3 ANSI INCITS 517-2015 . The SAT\-4 project
is near standardization and the most recent draft is sat4r06.pdf .
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
@@ -159,7 +159,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2006\-2018 Douglas Gilbert
+Copyright \(co 2006\-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.
diff --git a/doc/sg_write_x.8 b/doc/sg_write_x.8
index 122d950a..de9f10da 100644
--- a/doc/sg_write_x.8
+++ b/doc/sg_write_x.8
@@ -1,4 +1,4 @@
-.TH SG_WRITE_X "8" "May 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_WRITE_X "8" "January 2020" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_write_x \- SCSI WRITE normal/ATOMIC/SAME/SCATTERED/STREAM, ORWRITE commands
.SH SYNOPSIS
@@ -451,7 +451,7 @@ output version string then exit.
.TP
\fB\-w\fR, \fB\-\-wrprotect\fR=\fIWPR\fR
sets the WRPROTECT field (3 bits) in all sg_write_x commands apart from
-ORWRITE which has a 3 bit ORPROTECT field (and the synopsis shows \fiOPR\fR
+ORWRITE which has a 3 bit ORPROTECT field (and the synopsis shows \fIOPR\fR
to highlight the difference). In all cases \fIWPR\fR is placed
in that 3 bit field. The default value is zero which does not send any PI
in the data\-out buffer. \fIWPR\fR should be a value between 0 and 7.
@@ -587,7 +587,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2017 Douglas Gilbert
+Copyright \(co 2017\-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.
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 0b722069..35fe3196 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -383,7 +383,7 @@ void sg_set_warnings_strm(FILE * warnings_strm);
* least blen bytes long. If cmd_name is true then the command is prefixed
* by its SCSI command name (e.g. "VERIFY(10) [2f ...]". The command is
* shown as spaced separated pairs of hexadecimal digits (i.e. 0-9, a-f).
- * Each pair repesents byte. The leftmost pair of digits is cmdp[0] . If
+ * Each pair represents byte. The leftmost pair of digits is cmdp[0] . If
* sz <= 0 then this function tries to guess the length of the command. */
char *
sg_get_command_str(const uint8_t * cmdp, int sz, bool cmd_name, int blen,
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index d688f6eb..b89bb500 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2019 Douglas Gilbert.
+ * Copyright (c) 1999-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.
@@ -167,7 +167,7 @@ static char bin2hexascii[] = {'0', '1', '2', '3', '4', '5', '6', '7',
* least blen bytes long. If cmd_name is true then the command is prefixed
* by its SCSI command name (e.g. "VERIFY(10) [2f ...]". The command is
* shown as spaced separated pairs of hexadecimal digits (i.e. 0-9, a-f).
- * Each pair repesents byte. The leftmost pair of digits is cmdp[0] . If
+ * Each pair represents byte. The leftmost pair of digits is cmdp[0] . If
* sz <= 0 then this function tries to guess the length of the command. */
char *
sg_get_command_str(const uint8_t * cmdp, int sz, bool cmd_name, int blen,
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 7bec0678..6c0326c3 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2019 Douglas Gilbert.
+ * Copyright (c) 2007-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.
@@ -19,7 +19,7 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.70 20191226";
+const char * sg_lib_version_str = "2.72 20200125";
/* spc5r22, sbc4r17, zbc2r04 */
@@ -104,7 +104,8 @@ struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0x37, 0, "Read defect data(10)"},
/* SBC-3 r31 recommends Read defect data(12) */
{0x37, PDT_MCHANGER, "Initialize element status with range"},
- {0x38, 0, "Medium scan"},
+ {0x38, 0, "Format with preset scan"},
+ {0x38, PDT_OCRW, "Medium scan"},
{0x39, 0, "Compare"}, /* obsolete in SPC-4 r11 */
{0x3a, 0, "Copy and verify"}, /* obsolete in SPC-4 r11 */
{0x3b, 0, "Write buffer"},
diff --git a/scripts/55-scsi-sg3_id.rules b/scripts/55-scsi-sg3_id.rules
index 9117e2db..59c5e284 100644
--- a/scripts/55-scsi-sg3_id.rules
+++ b/scripts/55-scsi-sg3_id.rules
@@ -96,7 +96,7 @@ ENV{ID_WWN_WITH_EXTENSION}=="?*", ENV{ID_WWN}!="?*", \
PROGRAM="/bin/sh -c 'echo $env{ID_WWN_WITH_EXTENSION} | /bin/sed s/^\\\(0x.\\\{1,16\\\}\\\).*/\\1/'", \
ENV{ID_WWN}="$result"
-# ata_id compability
+# ata_id compatibility
ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_ATA}=="?*", ENV{ID_BUS}="ata", ENV{ID_ATA}="1", ENV{ID_SERIAL}="$env{SCSI_IDENT_LUN_ATA}"
ENV{ID_SERIAL_SHORT}!="?*", ENV{SCSI_VENDOR}=="ATA", ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_VENDOR}"
# Compat ID_SERIAL setting
diff --git a/scripts/58-scsi-sg3_symlink.rules b/scripts/58-scsi-sg3_symlink.rules
index 7c193089..2aacfec8 100644
--- a/scripts/58-scsi-sg3_symlink.rules
+++ b/scripts/58-scsi-sg3_symlink.rules
@@ -19,7 +19,7 @@ ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-
# 3: IEEE Extended
ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}"
ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}-part%n"
-# 4: EUI-64 identifer (prefix 2)
+# 4: EUI-64 identifier (prefix 2)
ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}"
ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}-part%n"
# 5: SCSI name identifier (prefix 8)
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 5dbc2c89..461c063a 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Wed Jan 01 2020 - dgilbert at interlog dot com
+* Sat Jan 25 2020 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.45
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 97513b76..f3782b2d 100644
--- a/src/sg_dd.c
+++ b/src/sg_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 - 2019 D. Gilbert and P. Allworth
+ * Copyright (C) 1999 - 2020 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)
@@ -66,7 +66,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "6.08 20191220";
+static const char * version_str = "6.09 20200117";
#define ME "sg_dd: "
@@ -94,6 +94,9 @@ static const char * version_str = "6.08 20191220";
#define READ_LONG_OPCODE 0x3E
#define READ_LONG_CMD_LEN 10
#define READ_LONG_DEF_BLK_INC 8
+#define VERIFY10 0x2f
+#define VERIFY12 0xaf
+#define VERIFY16 0x8f
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
@@ -519,14 +522,18 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
{
int sz_ind;
int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88};
- int ve_opcode[] = {0xff /* no VERIFY(6) */, 0x2f, 0xaf, 0x8f};
+ int ve_opcode[] = {0xff /* no VERIFY(6) */, VERIFY10, VERIFY12, VERIFY16};
int wr_opcode[] = {0xa, 0x2a, 0xaa, 0x8a};
memset(cdbp, 0, cdb_sz);
- if (dpo)
- cdbp[1] |= 0x10;
- if (fua)
- cdbp[1] |= 0x8;
+ if (is_verify)
+ cdbp[1] = 0x2; /* (BYTCHK=1) << 1 */
+ else {
+ if (dpo)
+ cdbp[1] |= 0x10;
+ if (fua)
+ cdbp[1] |= 0x8;
+ }
switch (cdb_sz) {
case 6:
sz_ind = 0;
@@ -657,6 +664,7 @@ sg_read_low(int sg_fd, uint8_t * buff, int blocks, int64_t from_block,
slen = io_hdr.sb_len_wr;
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
++recovered_errs;
@@ -1016,6 +1024,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
bool info_valid;
int res;
uint64_t io_addr = 0;
+ const char * op_str = do_verify ? "verifying" : "writing";
uint8_t wrCmd[MAX_SCSI_CDBSZ];
uint8_t senseBuff[SENSE_BUFF_LEN];
struct sg_io_hdr io_hdr;
@@ -1050,7 +1059,10 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
if (res < 0) {
if (ENOMEM == errno)
return -2;
- perror("writing (SG_IO) on sg device, error");
+ if (do_verify)
+ perror("verifying (SG_IO) on sg device, error");
+ else
+ perror("writing (SG_IO) on sg device, error");
return -1;
}
@@ -1059,6 +1071,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
res = sg_err_category3(&io_hdr);
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
++recovered_errs;
@@ -1068,16 +1081,16 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
pr2serr(" lba of last recovered error in this WRITE=0x%" PRIx64
"\n", io_addr);
if (verbose > 1)
- sg_chk_n_print3("writing", &io_hdr, true);
+ sg_chk_n_print3(op_str, &io_hdr, true);
} else {
- pr2serr("Recovered error: [no info] writing to block=0x%" PRIx64
- ", num=%d\n", to_block, blocks);
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ pr2serr("Recovered error: [no info] %s to block=0x%" PRIx64
+ ", num=%d\n", op_str, to_block, blocks);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
}
break;
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
return res;
case SG_LIB_CAT_NOT_READY:
++unrecovered_errs;
@@ -1085,7 +1098,7 @@ sg_write(int sg_fd, uint8_t * buff, int blocks, int64_t to_block,
return res;
case SG_LIB_CAT_MEDIUM_HARD:
default:
- sg_chk_n_print3("writing", &io_hdr, verbose > 1);
+ sg_chk_n_print3(op_str, &io_hdr, verbose > 1);
++unrecovered_errs;
if (ofp->coe) {
pr2serr(">> ignored errors for out blk=%" PRId64 " for %d "
diff --git a/src/sg_format.c b/src/sg_format.c
index f30a4e6d..24f94bf6 100644
--- a/src/sg_format.c
+++ b/src/sg_format.c
@@ -6,7 +6,7 @@
*
* Copyright (C) 2003 Grant Grundler grundler at parisc-linux dot org
* Copyright (C) 2003 James Bottomley jejb at parisc-linux dot org
- * Copyright (C) 2005-2019 Douglas Gilbert dgilbert at interlog dot com
+ * Copyright (C) 2005-2020 Douglas Gilbert dgilbert at interlog dot com
*
* 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
@@ -40,7 +40,7 @@
#include "sg_pr2serr.h"
#include "sg_pt.h"
-static const char * version_str = "1.60 20191220";
+static const char * version_str = "1.61 20200123";
#define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */
@@ -72,6 +72,11 @@ static const char * version_str = "1.60 20191220";
/* FORMAT UNIT (SBC) and FORMAT MEDIUM (SSC) share the same opcode */
#define SG_FORMAT_MEDIUM_CMD 0x4
#define SG_FORMAT_MEDIUM_CMDLEN 6
+
+/* FORMAT WITH PRESET (new in sbc4r18) */
+#define SG_FORMAT_WITH_PRESET_CMD 0x38
+#define SG_FORMAT_WITH_PRESET_CMDLEN 10
+
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
struct opts_t {
@@ -79,13 +84,15 @@ struct opts_t {
bool cmplst_given;
bool dry_run; /* -d */
bool early; /* -e */
- bool fwait; /* -w (negate for immed) */
+ bool fmtmaxlba; /* -b (only with F_WITH_PRESET) */
+ bool fwait; /* -w (negated form IMMED) */
bool ip_def; /* -I */
bool long_lba; /* -l */
bool mode6; /* -6 */
bool pinfo; /* -p, deprecated, prefer fmtpinfo */
bool poll_type; /* -x 0|1 */
bool poll_type_given;
+ bool preset; /* -E */
bool quick; /* -Q */
bool do_rcap16; /* -l */
bool resize; /* -r */
@@ -98,6 +105,7 @@ struct opts_t {
int ffmt; /* -t value; fast_format if > 0 */
int fmtpinfo;
int format; /* -F */
+ uint32_t p_id; /* set by argument of --preset=id */
int mode_page; /* -M value */
int pfu; /* -P value */
int pie; /* -q value */
@@ -120,6 +128,7 @@ static struct option long_options[] = {
{"dry_run", no_argument, 0, 'd'},
{"early", no_argument, 0, 'e'},
{"ffmt", required_argument, 0, 't'},
+ {"fmtmaxlba", no_argument, 0, 'b'},
{"fmtpinfo", required_argument, 0, 'f'},
{"format", no_argument, 0, 'F'},
{"help", no_argument, 0, 'h'},
@@ -131,6 +140,7 @@ static struct option long_options[] = {
{"pfu", required_argument, 0, 'P'},
{"pie", required_argument, 0, 'q'},
{"poll", required_argument, 0, 'x'},
+ {"preset", required_argument, 0, 'E'},
{"quick", no_argument, 0, 'Q'},
{"resize", no_argument, 0, 'r'},
{"rto_req", no_argument, 0, 'R'},
@@ -153,15 +163,17 @@ usage()
printf("Usage:\n"
" sg_format [--cmplst=0|1] [--count=COUNT] [--dcrt] "
"[--dry-run] [--early]\n"
- " [--ffmt=FFMT] [--fmtpinfo=FPI] [--format] "
- "[--help] [--ip-def]\n"
- " [--long] [--mode=MP] [--pfu=PFU] [--pie=PIE] "
- "[--pinfo]\n"
- " [--poll=PT] [--quick] [--resize] [--rto_req] "
- "[--security]\n"
- " [--six] [--size=LB_SZ] [--tape=FM] "
- "[--timeout=SECS] [--verbose]\n"
- " [--verify] [--version] [--wait] DEVICE\n"
+ " [--ffmt=FFMT] [--fmtmaxlba] [--fmtpinfo=FPI] "
+ "[--format] [--help]\n"
+ " [--ip-def] [--long] [--mode=MP] [--pfu=PFU] "
+ "[--pie=PIE]\n"
+ " [--pinfo] [--poll=PT] [--preset=ID] [--quick] "
+ "[--resize]\n"
+ " [--rto_req] [--security] [--six] [--size=LB_SZ] "
+ "[--tape=FM]\n"
+ " [--timeout=SECS] [--verbose] [--verify] "
+ "[--version] [--wait]\n"
+ " DEVICE\n"
" where:\n"
" --cmplst=0|1\n"
" -C 0|1 sets CMPLST bit in format cdb "
@@ -190,6 +202,8 @@ usage()
"count and size)\n"
" use thrice for FORMAT UNIT command "
"only\n"
+ " --fmtmaxlba|-b sets FMTMAXLBA field in FORMAT WITH "
+ "PRESET\n"
" --help|-h prints out this usage message\n"
" --ip-def|-I use default initialization pattern\n"
" --long|-l allow for 64 bit lbas (default: assume "
@@ -204,8 +218,12 @@ usage()
" --poll=PT|-x PT PT is poll type, 0 for test unit "
"ready\n"
" 1 for request sense (def: 0 (1 "
- "for tape))\n");
- printf(" --quick|-Q start format without pause for user "
+ "for tape and\n"
+ " format with preset))\n");
+ printf(" --preset=ID|-E ID do FORMAT WITH PRESET command "
+ "with PRESET\n"
+ " IDENTIFIER field set to ID\n"
+ " --quick|-Q start format without pause for user "
"intervention\n"
" (i.e. no time to reconsider)\n"
" --resize|-r resize (rather than format) to COUNT "
@@ -231,17 +249,19 @@ usage()
" --verbose|-v increase verbosity\n"
" --verify|-y sets VERIFY bit in FORMAT MEDIUM (tape)\n"
" --version|-V print version details and exit\n"
- " --wait|-w format command waits until format "
- "operation completes\n"
+ " --wait|-w format commands wait until format "
+ "operations complete\n"
" (default: set IMMED=1 and poll with "
"Test Unit Ready)\n\n"
"\tExample: sg_format --format /dev/sdc\n\n"
"This utility formats a SCSI disk [FORMAT UNIT] or resizes "
"it. Alternatively\nif '--tape=FM' is given formats a tape "
- "[FORMAT MEDIUM].\n\n");
- printf("WARNING: This utility will destroy all the data on "
- "DEVICE when '--format'\n\t or '--tape' is given. Check that "
- "you have specified the correct\n\t DEVICE.\n");
+ "[FORMAT MEDIUM]. Another alternative\nis doing the FORMAT "
+ "WITH PRESET command when '--preset=ID' is given.\n\n");
+ printf("WARNING: This utility will destroy all the data on the "
+ "DEVICE when\n\t '--format', '--tape=FM' or '--preset=ID' "
+ "is given. Double check\n\t that you have specified the "
+ "correct DEVICE.\n");
}
/* Invokes a SCSI FORMAT MEDIUM command (SSC). Return of 0 -> success,
@@ -302,6 +322,61 @@ sg_ll_format_medium(int sg_fd, bool verify, bool immed, int format,
return ret;
}
+/* Invokes a SCSI FORMAT WITH PRESET command (SBC). Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors */
+static int
+sg_ll_format_with_preset(int sg_fd, bool immed, bool fmtmaxlba,
+ uint32_t preset_id, int timeout, bool noisy,
+ int verbose)
+{
+ int ret, res, sense_cat;
+ uint8_t fwp_cdb[SG_FORMAT_WITH_PRESET_CMDLEN] =
+ {SG_FORMAT_WITH_PRESET_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ if (immed)
+ fwp_cdb[1] |= 0x80;
+ if (fmtmaxlba)
+ fwp_cdb[1] |= 0x40;
+ if (preset_id > 0)
+ sg_put_unaligned_be32(preset_id, fwp_cdb + 2);
+ if (verbose) {
+ char b[128];
+
+ pr2serr(" Format with preset cdb: %s\n",
+ sg_get_command_str(fwp_cdb,
+ SG_FORMAT_WITH_PRESET_CMDLEN,
+ false, sizeof(b), b));
+ }
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return sg_convert_errno(ENOMEM);
+ }
+ set_scsi_pt_cdb(ptvp, fwp_cdb, sizeof(fwp_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ res = do_scsi_pt(ptvp, sg_fd, timeout, verbose);
+ ret = sg_cmds_process_resp(ptvp, "format with preset", 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;
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
/* Return 0 on success, else see sg_ll_format_unit_v2() */
static int
scsi_format_unit(int fd, const struct opts_t * op)
@@ -493,7 +568,7 @@ scsi_format_medium(int fd, const struct opts_t * op)
tmout = op->timeout;
if (op->dry_run) {
res = 0;
- pr2serr("Due to --dry-run option bypassing FORMAT UNIT "
+ pr2serr("Due to --dry-run option bypassing FORMAT MEDIUM "
"command\n");
} else
res = sg_ll_format_medium(fd, op->verify, immed,
@@ -580,6 +655,114 @@ scsi_format_medium(int fd, const struct opts_t * op)
return 0;
}
+/* Return 0 on success, else see sg_ll_format_medium() above */
+static int
+scsi_format_with_preset(int fd, const struct opts_t * op)
+{
+ int res, progress, pr, rem, resp_len, tmout;
+ int vb = op->verbose;
+ bool immed = ! op->fwait;
+ char b[80];
+
+ if (immed)
+ tmout = SHORT_TIMEOUT;
+ else {
+ if (op->total_byte_count > EIGHT_TBYTE)
+ tmout = VLONG_FORMAT_TIMEOUT;
+ else if (op->total_byte_count > FOUR_TBYTE)
+ tmout = LONG_FORMAT_TIMEOUT;
+ else
+ tmout = FORMAT_TIMEOUT;
+ }
+ if (op->timeout > tmout)
+ tmout = op->timeout;
+ if (op->dry_run) {
+ res = 0;
+ pr2serr("Due to --dry-run option bypassing FORMAT WITH "
+ "PRESET command\n");
+ } else
+ res = sg_ll_format_with_preset(fd, immed, op->fmtmaxlba,
+ op->p_id, tmout, true, vb);
+ if (res) {
+ sg_get_category_sense_str(res, sizeof(b), b, vb);
+ pr2serr("Format with preset command: %s\n", b);
+ return res;
+ }
+ if (! immed)
+ return 0;
+
+ if (! op->dry_run)
+ printf("\nFormat with preset has started\n");
+ if (op->early) {
+ if (immed)
+ printf("Format continuing,\n Request sense can "
+ "be used to monitor progress\n");
+ return 0;
+ }
+
+ if (op->dry_run) {
+ printf("No point in polling for progress, so exit\n");
+ return 0;
+ }
+ if (! op->poll_type) {
+ for(;;) {
+ sleep_for(POLL_DURATION_SECS);
+ progress = -1;
+ res = sg_ll_test_unit_ready_progress(fd, 0, &progress,
+ true, (vb > 1) ? (vb - 1) : 0);
+ if (progress >= 0) {
+ pr = (progress * 100) / 65536;
+ rem = ((progress * 100) % 65536) / 656;
+ printf("Format in progress, %d.%02d%% done\n",
+ pr, rem);
+ } else
+ break;
+ }
+ }
+ if (op->poll_type || (SG_LIB_CAT_NOT_READY == res)) {
+ uint8_t * reqSense;
+ uint8_t * free_reqSense = NULL;
+
+ reqSense = sg_memalign(MAX_BUFF_SZ, 0, &free_reqSense, false);
+ if (NULL == reqSense) {
+ pr2serr("%s: unable to obtain heap for Request "
+ "Sense\n", __func__);
+ return sg_convert_errno(ENOMEM);
+ }
+ for(;;) {
+ sleep_for(POLL_DURATION_SECS);
+ memset(reqSense, 0x0, MAX_BUFF_SZ);
+ res = sg_ll_request_sense(fd, false, reqSense,
+ MAX_BUFF_SZ, false,
+ (vb > 1) ? (vb - 1) : 0);
+ if (res) {
+ pr2serr("polling with Request Sense command "
+ "failed [res=%d]\n", res);
+ break;
+ }
+ resp_len = reqSense[7] + 8;
+ if (vb > 1) {
+ pr2serr("Parameter data in hex:\n");
+ hex2stderr(reqSense, resp_len, 1);
+ }
+ progress = -1;
+ sg_get_sense_progress_fld(reqSense, resp_len,
+ &progress);
+ if (progress >= 0) {
+ pr = (progress * 100) / 65536;
+ rem = ((progress * 100) % 65536) / 656;
+ printf("Format in progress, %d.%02d%% done\n",
+ pr, rem);
+ } else
+ break;
+ }
+ if (free_reqSense)
+ free(free_reqSense);
+ }
+ printf("FORMAT WITH PRESET Complete\n");
+ return 0;
+}
+
#define VPD_DEVICE_ID 0x83
#define VPD_ASSOC_LU 0
#define VPD_ASSOC_TPORT 1
@@ -1033,6 +1216,7 @@ static int
parse_cmd_line(struct opts_t * op, int argc, char **argv)
{
int j;
+ int64_t ll;
op->cmplst = true; /* will be set false if FFMT > 0 */
op->mode_page = RW_ERROR_RECOVERY_PAGE;
@@ -1043,12 +1227,15 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
int c;
c = getopt_long(argc, argv,
- "c:C:dDef:FhIlm:M:pP:q:QrRs:St:T:vVwx:y6",
+ "bc:C:dDeE:f:FhIlm:M:pP:q:QrRs:St:T:vVwx:y6",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
+ case 'b':
+ op->fmtmaxlba = true;
+ break;
case 'c':
if (0 == strcmp("-1", optarg))
op->blk_count = -1;
@@ -1079,6 +1266,17 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
case 'e':
op->early = true;
break;
+ case 'E':
+ ll = sg_get_llnum(optarg);
+ if ((ll < 0) || (ll > UINT32_MAX)) {
+ pr2serr("bad argument to '--preset', need 32 "
+ "bit integer\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->p_id = (uint32_t)ll;
+ op->preset = true;
+ op->poll_type = 1; /* poll with REQUEST SENSE */
+ break;
case 'f':
op->fmtpinfo = sg_get_num(optarg);
if ((op->fmtpinfo < 0) || ( op->fmtpinfo > 3)) {
@@ -1240,9 +1438,10 @@ parse_cmd_line(struct opts_t * op, int argc, char **argv)
usage();
return SG_LIB_SYNTAX_ERROR;
}
- if (op->format && (op->tape >= 0)) {
- pr2serr("Cannot choose both '--format' and '--tape='; disk "
- "or tape, choose one only\n");
+ if (((int)(op->format > 0) + (int)(op->tape >= 0) + (int)op->preset)
+ > 1) {
+ pr2serr("Can choose only one of: '--format', '--tape=' and "
+ "'--preset='\n");
return SG_LIB_CONTRADICT;
}
if (op->ip_def && op->sec_init) {
@@ -1352,7 +1551,8 @@ main(int argc, char **argv)
goto out;
}
goto format_med;
- }
+ } else if (op->preset)
+ goto format_with_pre;
ret = fetch_block_desc(fd, dbuff, &calc_len, &bd_lb_sz, op);
if (ret) {
@@ -1428,7 +1628,6 @@ again_sp_false:
if (op->format) {
format_only:
-#if 1
if (op->quick)
goto skip_f_unit_reconsider;
printf("\nA FORMAT UNIT will commence in 15 seconds\n");
@@ -1455,9 +1654,6 @@ skip_f_unit_reconsider:
pr2serr(" try '-v' for more "
"information\n");
}
-#else
- pr2serr("FORMAT UNIT ignored, testing\n");
-#endif
}
goto out;
@@ -1487,8 +1683,35 @@ skip_f_med_reconsider:
if (res) {
pr2serr("FORMAT MEDIUM failed\n");
if (0 == vb)
- pr2serr(" try '-v' for more "
- "information\n");
+ pr2serr(" try '-v' for more information\n");
+ }
+ goto out;
+
+format_with_pre:
+ if (op->quick)
+ goto skip_f_with_pre_reconsider;
+ printf("\nA FORMAT WITH PRESET will commence in 15 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+ printf("\nA FORMAT WITH PRESET will commence in 10 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+ printf("\nA FORMAT WITH PRESET will commence in 5 seconds\n");
+ printf(" ALL data on %s will be DESTROYED\n",
+ op->device_name);
+ printf(" Press control-C to abort\n");
+ sleep_for(5);
+skip_f_with_pre_reconsider:
+ res = scsi_format_with_preset(fd, op);
+ ret = res;
+ if (res) {
+ pr2serr("FORMAT WITH PRESET failed\n");
+ if (0 == vb)
+ pr2serr(" try '-v' for more information\n");
}
out:
diff --git a/src/sg_inq.c b/src/sg_inq.c
index f1df8085..8aec3763 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2000-2019 D. Gilbert
+ * Copyright (C) 2000-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)
@@ -51,7 +51,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "2.03 20190913"; /* SPC-5 rev 22 */
+static const char * version_str = "2.04 20200123"; /* SPC-6 rev 01 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -108,6 +108,7 @@ static const char * version_str = "2.03 20190913"; /* SPC-5 rev 22 */
#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
#ifndef SG_NVME_VPD_NICR
#define SG_NVME_VPD_NICR 0xde
@@ -190,6 +191,7 @@ static struct svpd_values_name_t vpd_pg[] = {
"identification, target device only"},
#endif
{VPD_EXT_INQ, 0, -1, 0, "ei", "Extended inquiry data"},
+ {VPD_FORMAT_PRESETS, 0, 0, 0, "fp", "Format presets"},
{VPD_LB_PROVISIONING, 0, 0, 0, "lbpv", "Logical block provisioning "
"(SBC)"},
{VPD_MAN_NET_ADDR, 0, -1, 0, "mna", "Management network addresses"},
diff --git a/src/sg_luns.c b/src/sg_luns.c
index 555e14d6..5217ea98 100644
--- a/src/sg_luns.c
+++ b/src/sg_luns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2019 Douglas Gilbert.
+ * Copyright (c) 2004-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.
@@ -34,7 +34,7 @@
* and decodes the response.
*/
-static const char * version_str = "1.43 20190913";
+static const char * version_str = "1.44 20200115";
#define MAX_RLUNS_BUFF_LEN (1024 * 1024)
#define DEF_RLUNS_BUFF_LEN (1024 * 8)
@@ -252,6 +252,9 @@ decode_lun(const char * leadin, const uint8_t * lunp, bool lu_cong,
case 5:
printf("%sMANAGEMENT PROTOCOL %s\n", l_leadin, b);
break;
+ case 6:
+ printf("%sTARGET COMMANDS %s\n", l_leadin, b);
+ break;
default:
if (do_hex)
printf("%s%s 0x%02x\n", l_leadin, b, x);
diff --git a/src/sg_modes.c b/src/sg_modes.c
index dc8c4691..06d96334 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.69 20200111";
+static const char * version_str = "1.71 20200121";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -253,6 +253,15 @@ static struct page_code_desc pc_desc_t_adc[] = {
{0x0, 0x0, NULL, NULL},
};
+static struct page_code_desc pc_desc_zbc[] = {
+ {0x1, 0x0, "rw", "Read-Write error recovery"},
+ {0x7, 0x0, "ve", "Verify error recovery"},
+ {0x8, 0x0, "ca", "Caching"},
+ {0xa, 0x2, "atag", "Application tag"},
+ {0x1c, 0x1, "bc", "Background control"},
+ {0x0, 0x0, NULL, NULL},
+};
+
struct pc_desc_group pcd_gr_arr[] = {
{pc_desc_common, "common"},
{pc_desc_disk, "disk"},
@@ -263,6 +272,7 @@ struct pc_desc_group pcd_gr_arr[] = {
{pc_desc_ses, "enclosure"},
{pc_desc_rbc, "reduced block"},
{pc_desc_adc, "adc"},
+ {pc_desc_zbc, "zbc"},
{pc_desc_t_fcp, "transport: FCP"},
{pc_desc_t_spi4, "transport: SPI"},
{pc_desc_t_sas, "transport: SAS"},
@@ -821,6 +831,9 @@ get_mpage_tbl_size(int scsi_ptype, int * sizep)
case PDT_ADC: /* automation device/interface */
*sizep = count_desc_elems(pc_desc_adc);
return &pc_desc_adc[0];
+ case PDT_ZBC:
+ *sizep = count_desc_elems(pc_desc_zbc);
+ return &pc_desc_zbc[0];
}
*sizep = 0;
return NULL;
@@ -1421,7 +1434,7 @@ main(int argc, char * argv[])
hex2stdout(rsp_buff, headerlen, 1);
goto fini;
}
- if (0 == inq_pdt)
+ if ((PDT_DISK == inq_pdt) || (PDT_ZBC == inq_pdt))
printf(" Mode data length=%d, medium type=0x%.2x, WP=%d,"
" DpoFua=%d, longlba=%d\n", md_len, medium_type,
!!(specific & 0x80), !!(specific & 0x10), (int)longlba);
@@ -1448,7 +1461,7 @@ main(int argc, char * argv[])
len = 16;
density_code_off = 8;
}
- else if (0 == inq_pdt) {
+ else if ((PDT_DISK == inq_pdt) || (PDT_ZBC == inq_pdt)) {
printf("> Direct access device block descriptors:\n");
density_code_off = 4;
}
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index a383ef84..571f92e3 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -1,7 +1,7 @@
/* This code is does a SCSI READ CAPACITY command on the given device
* and outputs the result.
*
- * Copyright (C) 1999 - 2018 D. Gilbert
+ * Copyright (C) 1999 - 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)
@@ -36,7 +36,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "4.04 20180911";
+static const char * version_str = "4.05 20200122";
#define ME "sg_readcap: "
@@ -83,12 +83,14 @@ struct opts_t {
static void
usage()
{
- pr2serr("Usage: sg_readcap [--brief] [--help] [--hex] [--lba=LBA] "
- "[--long] [--16]\n"
+ pr2serr("Usage: sg_readcap [--16] [--brief] [--help] [--hex] "
+ "[--lba=LBA] [--long]\n"
" [--pmi] [--raw] [--readonly] [--verbose] "
"[--version]\n"
" [--zbc] DEVICE\n"
" where:\n"
+ " --16 use READ CAPACITY (16) cdb (same as "
+ "--long)\n"
" --brief|-b brief, two hex numbers: number of blocks "
"and block size\n"
" --help|-h print this usage message and exit\n"
@@ -99,8 +101,6 @@ usage()
"valid with '--pmi']\n"
" --long|-l use READ CAPACITY (16) cdb (def: use "
"10 byte cdb)\n"
- " --16 use READ CAPACITY (16) cdb (same as "
- "--long)\n"
" --pmi|-p partial medium indicator (without this "
"option shows\n"
" total disk capacity) [made obsolete in "
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 3be9f5f0..cf390f19 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019 Douglas Gilbert.
+ * 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.
@@ -38,7 +38,7 @@
* and decodes the response. Based on zbc-r02.pdf
*/
-static const char * version_str = "1.19 20191226";
+static const char * version_str = "1.20 20200122";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -472,8 +472,8 @@ main(int argc, char * argv[])
goto the_end;
}
same = reportZonesBuff[4] & 0xf;
- printf(" Same=%d: %s\n\n", same, same_desc_arr[same]);
- printf(" Maximum LBA: 0x%" PRIx64 "\n",
+ printf(" Same=%d: %s\n", same, same_desc_arr[same]);
+ printf(" Maximum LBA: 0x%" PRIx64 "\n\n",
sg_get_unaligned_be64(reportZonesBuff + 8));
zones = (len - 64) / 64;
for (k = 0, bp = reportZonesBuff + 64; k < zones; ++k, bp += 64) {
diff --git a/src/sg_seek.c b/src/sg_seek.c
index 9084fd75..f99c1f0f 100644
--- a/src/sg_seek.c
+++ b/src/sg_seek.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Douglas Gilbert.
+ * Copyright (c) 2018-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.
@@ -49,7 +49,7 @@
* to that LBA ...
*/
-static const char * version_str = "1.07 20180911";
+static const char * version_str = "1.08 20200115";
#define BACKGROUND_CONTROL_SA 0x15
@@ -418,7 +418,10 @@ fini:
}
}
if (0 == verbose) {
- if (! sg_if_can2stderr("sg_seek failed: ", ret))
+ const char * e_str = (SG_LIB_CAT_CONDITION_MET == ret) ?
+ "sg_seek: " : "sg_seek: failed";
+
+ if (! sg_if_can2stderr(e_str, ret))
pr2serr("Some error occurred, try again with '-v' "
"or '-vv' for more information\n");
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index f18d8096..b91261af 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2019 Douglas Gilbert.
+ * Copyright (c) 2006-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.
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.56 20191204"; /* spc5r22 + sbc4r17 */
+static const char * version_str = "1.57 20200123"; /* spc6r01 + sbc4r18 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -78,6 +78,7 @@ static const char * version_str = "1.56 20191204"; /* spc5r22 + sbc4r17 */
#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
/* Device identification VPD page associations */
@@ -210,6 +211,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_DTDE_ADDRESS, 0, 1, "dtde",
"Data transfer device element address (SSC)"},
{VPD_EXT_INQ, 0, -1, "ei", "Extended inquiry data"},
+ {VPD_FORMAT_PRESETS, 0, 0, "fp", "Format presets"},
{VPD_IMP_OP_DEF, 0, -1, "iod",
"Implemented operating definition (obsolete)"},
{VPD_LB_PROTECTION, 0, 0, "lbpro", "Logical block protection (SSC)"},
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 385826c6..e3a1b3d1 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -108,7 +108,7 @@
using namespace std;
-static const char * version_str = "1.64 20200110";
+static const char * version_str = "1.66 20200120";
#ifdef __GNUC__
#ifndef __clang__
@@ -138,6 +138,8 @@ static const char * version_str = "1.64 20200110";
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
#define SGP_READ10 0x28
+#define SGP_PRE_FETCH10 0x34
+#define SGP_PRE_FETCH16 0x90
#define SGP_VERIFY10 0x2f
#define SGP_WRITE10 0x2a
#define DEF_NUM_THREADS 4
@@ -247,6 +249,7 @@ typedef struct global_collection
bool mrq_async; /* either mrq_immed or no_waitq flags given */
bool unbalanced_mrq; /* so _not_ sg->sg request sharing sync mrq */
bool verify; /* don't copy, verify like Unix: cmp */
+ bool prefetch; /* for verify: do PF(b),RD(a),V(b)_a_data */
const char * infp;
const char * outfp;
const char * out2fp;
@@ -348,12 +351,14 @@ static pthread_t sig_listen_thread_id;
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
static void sg_in_rd_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr);
-static void sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2);
+static void sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2,
+ bool prefetch);
static bool normal_in_rd(Rq_elem * rep, int blocks);
static void normal_out_wr(Rq_elem * rep, int blocks);
static int sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
- bool is_wr2);
-static int sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2);
+ bool is_wr2, bool prefetch);
+static int sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2,
+ bool prefetch);
static int sg_in_open(Gbl_coll *clp, const char *inf, uint8_t **mmpp,
int *mmap_len);
static int sg_out_open(Gbl_coll *clp, const char *outf, uint8_t **mmpp,
@@ -826,9 +831,10 @@ usage(int pg_num)
"[fua=0|1|2|3]\n"
" [mrq=[IO,]NRQS[,C]] [of2=OFILE2] [ofreg=OFREG] "
"[sync=0|1]\n"
- " [thr=THR] [time=0|1] [verbose=VERB] [--dry-run] "
- "[--verbose]\n"
- " [--verify] [--version]\n\n"
+ " [thr=THR] [time=0|1] [verbose=VERB] "
+ "[--dry-run]\n"
+ " [--prefetch] [--verbose] [--verify] "
+ "[--version]\n\n"
" where the main options (shown in first group above) are:\n"
" bs must be device logical block size (default "
"512)\n"
@@ -851,6 +857,7 @@ usage(int pg_num)
" seek block position to start writing to OFILE\n"
" skip block position to start reading from IFILE\n"
" --help|-h output this usage message then exit\n"
+ " --prefetch|-p with verify: do pre-fetch first\n"
" --verify|-x do a verify (compare) operation [def: do a "
"copy]\n"
" --version|-V output version string then exit\n\n"
@@ -996,7 +1003,17 @@ page4:
"is intended to be\na temporary state. It should not block "
"but does sometimes (e.g. in\nblock_get_request()). Even so "
"that blockage should be short and if not\nthere is a "
- "problem.\n");
+ "problem.\n\n");
+ pr2serr("--verify :\n"
+ "For comparing IFILE with OFILE. Does repeated sequences of: "
+ "READ(ifile)\nand uses data returned to send to VERIFY(ofile, "
+ "BYTCHK=1). So the OFILE\ndevice/disk is doing the actual "
+ "comparison. Stops on first miscompare.\n\n");
+ pr2serr("--prefetch :\n"
+ "Used with --verify option. Prepends a PRE-FETCH(ofile, IMMED) "
+ "to verify\nsequence. This should speed the trailing VERIFY by "
+ "making sure that\nthe data it needs for the comparison is "
+ "already in its cache.\n");
return;
}
@@ -1499,11 +1516,11 @@ skip_force_out_sequence:
wr_blks = rep->num_blks;
if (out_is_sg) {
if (rep->swait && rep->has_share) {
- /* done already in sg_in_out_interleave() */
+ /* done already in sg_in_out_interleave() */
status = pthread_mutex_unlock(&clp->out_mutex);
if (0 != status) err_exit(status, "unlock out_mutex");
} else /* release out_mtx */
- sg_out_wr_cmd(rep, deferred_arr, false);
+ sg_out_wr_cmd(rep, deferred_arr, false, clp->prefetch);
} else if (FT_DEV_NULL == clp->out_type) {
/* skip actual write operation */
wr_blks = 0;
@@ -1525,7 +1542,7 @@ skip_force_out_sequence:
status = pthread_mutex_lock(&clp->out2_mutex);
if (0 != status) err_exit(status, "lock out2_mutex");
/* releases out2_mutex mid operation */
- sg_out_wr_cmd(rep, deferred_arr, true);
+ sg_out_wr_cmd(rep, deferred_arr, true, false);
pthread_cleanup_pop(0);
}
@@ -1806,7 +1823,7 @@ sg_in_rd_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr)
int res, status, pack_id;
while (1) {
- res = sg_start_io(rep, def_arr, pack_id, false);
+ res = sg_start_io(rep, def_arr, pack_id, false, false);
if (1 == res)
err_exit(ENOMEM, "sg starting in command");
else if (res < 0) {
@@ -1821,7 +1838,7 @@ sg_in_rd_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr)
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
- res = sg_finish_io(rep->wr, rep, pack_id, false);
+ res = sg_finish_io(rep->wr, rep, pack_id, false, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -1926,7 +1943,7 @@ sg_wr_swap_share(Rq_elem * rep, int to_fd, bool before)
/* Enters this function holding out_mutex */
static void
-sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
+sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2, bool prefetch)
{
int res, status, pack_id;
Gbl_coll * clp = rep->clp;
@@ -1935,8 +1952,49 @@ sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
if (rep->has_share && is_wr2)
sg_wr_swap_share(rep, rep->out2fd, true);
+ if (prefetch) {
+again:
+ res = sg_start_io(rep, def_arr, pack_id, is_wr2, true);
+ if (1 == res)
+ err_exit(ENOMEM, "sg starting out command");
+ else if (res < 0) {
+ pr2serr_lk("%soutputting from sg failed, blk=%" PRId64 "\n",
+ my_name, rep->oblk);
+ status = pthread_mutex_unlock(mutexp);
+ if (0 != status) err_exit(status, "unlock out_mutex");
+ stop_both(clp);
+ goto fini;
+ }
+ /* Now release in mutex to let other reads run in parallel */
+ status = pthread_mutex_unlock(mutexp);
+ if (0 != status) err_exit(status, "unlock out_mutex");
+
+ res = sg_finish_io(rep->wr, rep, pack_id, is_wr2, true);
+ switch (res) {
+ case SG_LIB_CAT_ABORTED_COMMAND:
+ case SG_LIB_CAT_UNIT_ATTENTION:
+ /* try again with same addr, count info */
+ /* now re-acquire out mutex for balance */
+ /* N.B. This re-write could now be out of write sequence */
+ status = pthread_mutex_lock(mutexp);
+ if (0 != status) err_exit(status, "lock out_mutex");
+ goto again;
+ case SG_LIB_CAT_CONDITION_MET:
+ case 0:
+ status = pthread_mutex_lock(mutexp);
+ if (0 != status) err_exit(status, "unlock out_mutex");
+ break;
+ default:
+ pr2serr_lk("error finishing sg prefetch command (%d)\n", res);
+ if (exit_status <= 0)
+ exit_status = res;
+ stop_both(clp);
+ goto fini;
+ }
+ }
+
while (1) {
- res = sg_start_io(rep, def_arr, pack_id, is_wr2);
+ res = sg_start_io(rep, def_arr, pack_id, is_wr2, false);
if (1 == res)
err_exit(ENOMEM, "sg starting out command");
else if (res < 0) {
@@ -1951,7 +2009,7 @@ sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
status = pthread_mutex_unlock(mutexp);
if (0 != status) err_exit(status, "unlock out_mutex");
- res = sg_finish_io(rep->wr, rep, pack_id, is_wr2);
+ res = sg_finish_io(rep->wr, rep, pack_id, is_wr2, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -1978,6 +2036,7 @@ sg_out_wr_cmd(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
/* FALL THROUGH */
#endif
#endif
+ case SG_LIB_CAT_CONDITION_MET:
case 0:
if (! is_wr2) {
status = pthread_mutex_lock(mutexp);
@@ -2019,7 +2078,7 @@ chk_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
int n_cmpl = ctl_v4p->info;
int n_good = 0;
int vb = clp->debug;
- int k, slen;
+ int k, slen, sstatus;
uint32_t good_inblks = 0;
uint32_t good_outblks = 0;
const struct sg_io_v4 * a_np = a_v4p;
@@ -2050,8 +2109,9 @@ chk_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
v4hdr_out_lk("cop", ctl_v4p, id);
}
ok = true;
- if (a_np->device_status || a_np->transport_status ||
- a_np->driver_status) {
+ sstatus = a_np->device_status;
+ if ((sstatus && (SAM_STAT_CONDITION_MET != sstatus)) ||
+ a_np->transport_status || a_np->driver_status) {
ok = false;
if (SAM_STAT_CHECK_CONDITION != a_np->device_status) {
pr2serr_lk("[%d] %s, a_n[%d]:\n", id, __func__, k);
@@ -2614,7 +2674,7 @@ fini:
/* Returns 0 on success, 1 if ENOMEM error else -1 for other errors. */
static int
sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
- bool is_wr2)
+ bool is_wr2, bool prefetch)
{
Gbl_coll * clp = rep->clp;
bool wr = rep->wr;
@@ -2640,9 +2700,11 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
b_len = sizeof(b);
if (wr) {
fd = is_wr2 ? rep->out2fd : rep->outfd;
- if (clp->verify)
+ if (clp->verify) {
crwp = is_wr2 ? "verifying2" : "verifying";
- else
+ if (prefetch)
+ crwp = is_wr2 ? "prefetch2" : "prefetch";
+ } else
crwp = is_wr2 ? "writing2" : "writing";
} else {
fd = rep->infd;
@@ -2656,6 +2718,18 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
my_name, blk, rep->num_blks);
return -1;
}
+ if (prefetch) {
+ if (cdbsz == 10)
+ rep->cmd[0] = SGP_PRE_FETCH10;
+ else if (cdbsz == 16)
+ rep->cmd[0] = SGP_PRE_FETCH16;
+ else {
+ pr2serr_lk("%sbad PRE-FETCH build, start_blk=%" PRId64 ", "
+ "blocks=%d\n", my_name, blk, rep->num_blks);
+ return -1;
+ }
+ rep->cmd[1] = 0x2; /* set IMMED (no fua or dpo) */
+ }
if (mmap && (rep->outregfd >= 0))
flags |= SG_FLAG_MMAP_IO;
if (noxfer)
@@ -2703,15 +2777,22 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
lk_print_command_len(prefix, rep->cmd, cdbsz, lock);
}
if (v4)
- goto do_v4;
+ goto do_v4; // <<<<<<<<<<<<<<< look further down
memset(hp, 0, sizeof(struct sg_io_hdr));
hp->interface_id = 'S';
hp->cmd_len = cdbsz;
hp->cmdp = rep->cmd;
- hp->dxfer_direction = wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- hp->dxfer_len = clp->bs * rep->num_blks;
hp->dxferp = get_buffp(rep);
+ hp->dxfer_len = clp->bs * rep->num_blks;
+ if (!wr)
+ hp->dxfer_direction = SG_DXFER_FROM_DEV;
+ else if (prefetch) {
+ hp->dxfer_direction = SG_DXFER_NONE;
+ hp->dxfer_len = 0;
+ hp->dxferp = NULL;
+ } else
+ hp->dxfer_direction = SG_DXFER_TO_DEV;
hp->mx_sb_len = sizeof(rep->sb);
hp->sbp = rep->sb;
hp->timeout = DEF_TIMEOUT;
@@ -2752,8 +2833,13 @@ do_v4:
h4p->request_len = cdbsz;
h4p->request = (uint64_t)rep->cmd;
if (wr) {
- h4p->dout_xfer_len = clp->bs * rep->num_blks;
- h4p->dout_xferp = (uint64_t)get_buffp(rep);
+ if (prefetch) {
+ h4p->dout_xfer_len = 0; // din_xfer_len is also 0
+ h4p->dout_xferp = 0;
+ } else {
+ h4p->dout_xfer_len = clp->bs * rep->num_blks;
+ h4p->dout_xferp = (uint64_t)get_buffp(rep);
+ }
} else if (rep->num_blks > 0) {
h4p->din_xfer_len = clp->bs * rep->num_blks;
h4p->din_xferp = (uint64_t)get_buffp(rep);
@@ -2855,7 +2941,7 @@ do_v4:
-> try again, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_MEDIUM_HARD,
-1 other errors */
static int
-sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2)
+sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2, bool prefetch)
{
Gbl_coll * clp = rep->clp;
bool v4 = wr ? clp->out_flags.v4 : clp->in_flags.v4;
@@ -2872,8 +2958,11 @@ sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2)
if (wr) {
fd = is_wr2 ? rep->out2fd : rep->outfd;
cp = is_wr2 ? "writing2" : "writing";
- if (clp->verify)
+ if (clp->verify) {
cp = is_wr2 ? "verifying2" : "verifying";
+ if (prefetch)
+ cp = is_wr2 ? "prefetch2" : "prefetch";
+ }
} else {
fd = rep->infd;
cp = "reading";
@@ -2915,6 +3004,7 @@ sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2)
res = sg_err_category3(hp);
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
lk_chk_n_print3(cp, hp, false);
@@ -2983,6 +3073,7 @@ do_v4:
h4p->response_len);
switch (res) {
case SG_LIB_CAT_CLEAN:
+ case SG_LIB_CAT_CONDITION_MET:
break;
case SG_LIB_CAT_RECOVERED:
lk_chk_n_print4(cp, h4p, false);
@@ -3042,7 +3133,7 @@ sg_in_out_interleave(Gbl_coll *clp, Rq_elem * rep, mrq_arr_t & def_arr)
while (1) {
/* start READ */
- res = sg_start_io(rep, def_arr, pid_read, false);
+ res = sg_start_io(rep, def_arr, pid_read, false, false);
if (1 == res)
err_exit(ENOMEM, "sg interleave starting in command");
else if (res < 0) {
@@ -3056,7 +3147,7 @@ sg_in_out_interleave(Gbl_coll *clp, Rq_elem * rep, mrq_arr_t & def_arr)
/* start WRITE */
rep->wr = true;
- res = sg_start_io(rep, def_arr, pid_write, false);
+ res = sg_start_io(rep, def_arr, pid_write, false, false);
if (1 == res)
err_exit(ENOMEM, "sg interleave starting out command");
else if (res < 0) {
@@ -3079,7 +3170,7 @@ read_complet:
/* finish READ */
rep->wr = false;
- res = sg_finish_io(rep->wr, rep, pid_read, false);
+ res = sg_finish_io(rep->wr, rep, pid_read, false, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -3139,7 +3230,7 @@ write_complet:
#endif
/* finish WRITE, no lock held */
rep->wr = true;
- res = sg_finish_io(rep->wr, rep, pid_write, false);
+ res = sg_finish_io(rep->wr, rep, pid_write, false, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -3671,6 +3762,10 @@ parse_cmdline_sanity(int argc, char * argv[], Gbl_coll * clp, char * inf,
n = num_chs_in_str(key + 1, keylen - 1, 'h');
clp->help += n;
res += n;
+ n = num_chs_in_str(key + 1, keylen - 1, 'p');
+ if (n > 0)
+ clp->prefetch = true;
+ res += n;
n = num_chs_in_str(key + 1, keylen - 1, 'v');
if (n > 0)
verbose_given = true;
@@ -3696,6 +3791,9 @@ parse_cmdline_sanity(int argc, char * argv[], Gbl_coll * clp, char * inf,
else if ((0 == strncmp(key, "--help", 6)) ||
(0 == strcmp(key, "-?")))
++clp->help;
+ else if ((0 == strncmp(key, "--prefetch", 10)) ||
+ (0 == strncmp(key, "--pre-fetch", 11)))
+ clp->prefetch = true;
else if (0 == strncmp(key, "--verb", 6)) {
verbose_given = true;
++clp->debug; /* --verbose */