| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" |
| content="text/html; charset=iso-8859-1"> |
| <meta name="keywords" content="Linux, SCSI, sg_dd, dd variant"> |
| <meta name="GENERATOR" |
| content="Mozilla/4.79 [en] (X11; U; Linux 2.5.31 i686) [Netscape]"> |
| <title>Linux sg_dd utility (a dd variant)</title> |
| </head> |
| <body alink="#ff0000" background="paper.jpg" bgcolor="#ffffff" |
| link="#0000ff" text="#000000" vlink="#000080"> |
| <center> |
| <h1> The Linux sg_dd utility<br> |
| </h1> |
| </center> |
| <a href="#Introduction">Introduction</a> <br> |
| <a href="#dd_like_features">dd like features</a> <br> |
| <a href="#sg_dd_extras">sg_dd extras</a><br> |
| <a href="#coe">Continue on error (coe)</a> <br> |
| <a href="#Recovered_errors">Recovered errors</a> <br> |
| <a href="#Verbose">Verbose</a><br> |
| <a href="#Conclusion">Conclusion</a><br> |
| |
| <h2><a name="Introduction"></a>Introduction</h2> |
| The <span style="font-weight: bold;">sg_dd</span> utility is a variant |
| of the standard Unix command <span style="font-weight: bold;">dd</span> |
| which |
| copies files. The sg_dd utility is specialized for devices that use the |
| SCSI command set in the Linux operating system. The sg_dd utility is |
| found in the <a href="u_index.html">sg3_utils</a> package which |
| targets the linux kernel 2.4 and |
| 2.6 series.<br> |
| <br> |
| Not all SCSI device types are supported by the sg_dd utility. Obviously |
| those device types that deal with enclosures and medium changers don't |
| have addressable blocks and are not supported. The supported device |
| types are direct access devices (e.g. disks) and cd/dvd devices. The |
| SCSI tape device type is not be supported (but could be to a limited |
| degree). When instructed, the sg_dd utility issues SCSI |
| commands that are defined in SPC-3 (primary commands), SBC-2 (commands |
| for direct access devices (e.g. disks)) and MMC-4 (commands for CD/DVD |
| devices). These SCSI command sets can be found at <a |
| href="http://www.t10.org/">www.t10.org</a> |
| . <br> |
| <br> |
| It is becoming common for non-SCSI devices (e.g. ATA disks) to appear |
| as SCSI devices to an operating system via a protocol conversion in an |
| external enclosure and via some transport such as USB or IEEE 1394. The |
| sg_dd utility should work with most of these devices as it tends to use |
| exactly the same SCSI commands that the normal block layer would uses. |
| However, advanced options (e.g. using the 'cdbsz' and 'fua') most |
| likely will be ignored. Apart from CD players over 10 years old, almost |
| all CD/DVD players use the Multi Media Command set (MMC or |
| MMC-2,3,4,5) as their native command set. The fact that the most common |
| transport is ATAPI (i.e. the ATA packet interface) is irrelevant, to |
| the |
| sg_dd utility they are SCSI devices.<br> |
| <br> |
| This page outlines the features of the sg_dd utility version 5.38 found |
| in the <a href="u_index.html">sg3_utils</a> version 1.13 package. This |
| was released on the 13th |
| March 2005.<br> |
| <h2><a name="dd_like_features"></a> dd like features</h2> |
| The basic syntax of the sg_dd utility is the same as the dd command in |
| Unix. That said, the syntax of the dd command in Unix is different from |
| almost all other standard Unix commands. Those familiar with the dd |
| command |
| should not be too surprised by the syntax and semantic of the sg_dd |
| utility. Those not familiar with the dd syntax should be very careful, |
| especially with the 'of' and 'seek' options, both with dd and sg_dd. |
| The recent GNU implementation of the dd command is used as a reference |
| point.<br> |
| <br> |
| The main options of dd are:<br> |
| <ul> |
| <li>if=<input_file></li> |
| <li>of=<output_file></li> |
| <li>bs=<block_size></li> |
| <li>count=<count_of_blocks></li> |
| </ul> |
| Both dd and sg_dd given these options with suitable arguments will copy |
| (bs * count) bytes from the beginning of <input_file> to the |
| beginning of <output_file>. One restriction that sg_dd imposes |
| when either the <input_file> or <output_file> are accessed |
| via SCSI commands is that <block_size> must match that of the |
| device. Further, if both the <input_file> and <output_file> |
| are accessed via SCSI commands then <block_size> must match that |
| of both devices. In both dd and sg_dd if the if=<input_file> |
| option is not given then stdin is assumed. In both dd and sg_dd if |
| of=<output_file> is not given then stdout is assumed.<br> |
| <br> |
| The following extensions are found in sg_dd. An <input_file> of |
| "-" is interpreted as stdin; an <output_file> of "-" is |
| interpreted as stdout while an <output_file> of "." is |
| interpreted as <span style="font-family: monospace;">/dev/null</span>. |
| [dd interprets input and output file names of |
| "-" literally. dd interprets an output file of "." as the current |
| directory and will not accept it.]<br> |
| <br> |
| If the 'count' option is not given then an attempt is made to determine |
| the remaining blocks in the file, device or partition. If the input |
| file is stdin and no count is given then a copy will continue until an |
| EOF is detected on the input stream (or something else goes wrong). If |
| the 'count' option is not given then the remaining blocks on both the |
| input and output files are determined (if possible) and if both are |
| found then the minimum of |
| the two counts is used. The 'skip' option for an input file and |
| the 'seek' option for an output file are taken into account when |
| calculating the remaining number of blocks in a file, device or |
| partition.<br> |
| <br> |
| If the 'count' option is given then no further checks regarding the |
| remaining length of the input and output files are done and the sg_dd |
| will attempt to copy that number of blocks. A 'count=0' option is valid |
| and all the normal preparations are made including files being opened |
| but no copy takes place. Hence the 'count=0' option can be used to |
| check the syntax is in order and the files are present (see the |
| "Verbose" section below).<br> |
| <br> |
| Other dd options supported by sg_dd:<br> |
| <ul> |
| <li>seek=<n_blocks_of></li> |
| <li>skip=<n_blocks_if></li> |
| <li>ibs=<block_size></li> |
| <li>obs=<block_size></li> |
| </ul> |
| If ibs and obs are given to sg_dd then they must be the same as bs |
| (i.e. they are essentially dummies). Both seek and skip are origin zero |
| and default to zero (i.e the start of the output and input files |
| respectively). The 'skip' option cannot be used on an input stream |
| (e.g. stdin) while the 'seek' option cannot be used on an output stream |
| (e.g. stdout).<br> |
| <br> |
| All numeric arguments can take a multiplier suffix. From sg3_utils |
| version 1.13 sg_dd's multiplier prefixes have been brought into line |
| with those of GNU's dd (in coreutils post a change on 2001-12-18):<br> |
| <br> |
| <table style="width: 50%; text-align: left;" border="1" cellpadding="2" |
| cellspacing="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">Multiplier</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">Meaning</span><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">x<n><br> |
| </td> |
| <td style="vertical-align: top;">*<n><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">c<br> |
| </td> |
| <td style="vertical-align: top;">*1<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">w<br> |
| </td> |
| <td style="vertical-align: top;">*2<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">b<br> |
| </td> |
| <td style="vertical-align: top;">*512<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">k K KiB<br> |
| </td> |
| <td style="vertical-align: top;">*1024<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">KB<br> |
| </td> |
| <td style="vertical-align: top;">*1000<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">m M MiB<br> |
| </td> |
| <td style="vertical-align: top;">*1048576 </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">MB<br> |
| </td> |
| <td style="vertical-align: top;">*1000000<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">g G GiB<br> |
| </td> |
| <td style="vertical-align: top;">2**30<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">GB<br> |
| </td> |
| <td style="vertical-align: top;">10**9<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">t T TiB<br> |
| </td> |
| <td style="vertical-align: top;">2**40 </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">TB<br> |
| </td> |
| <td style="vertical-align: top;">10**12<br> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <br> |
| The pattern that starts with "k" and proceeds to "m", "g" and "t" then |
| to "p", "e", "z" and "y" (not shown in above table). sg_dd only |
| implements as far as "p" (10**15 or 2**50). sg_dd only allows |
| multipliers based on "t" and "p" for 'count', 'skip' and 'seek'.<br> |
| <br> |
| sg_dd allows numeric arguments to be given in hexadecimal in which case |
| they must be prefixed by either "0x" or "0X". A numeric argument cannot |
| both be in hex and have a suffix multiplier. Hence "0x9" is interpreted |
| as hexadecimal 9 [not (0 * 9)==0]. This is valid "2x4x0xa" and yields |
| 80 (but it isn't very clear).<br> |
| <br> |
| The following dd options are <span style="font-weight: bold;">not</span> |
| supported by sg_dd:<br> |
| <ul> |
| <li>cbs=<bytes></li> |
| <li>conv=<keyword></li> |
| </ul> |
| Basically sg_dd does not supported the conversion features of dd. If a |
| conversion is really needed then sg_dd could be piped through dd (or |
| vice versa).<br> |
| <h2><a name="sg_dd_extras"></a>sg_dd extras</h2> |
| The extra options of sg_dd (not found in GNU's dd) are:<br> |
| <br> |
| <ul> |
| </ul> |
| <table style="width: 100%; text-align: left;" border="1" cellpadding="2" |
| cellspacing="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">extra |
| options in sg_dd</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">default</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">Brief |
| description</span><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">append=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">append to output file (rather |
| than overwrite)<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">blk_sgio=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">when set access devices via SCSI |
| commands (SG_IO)<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">bpt<br> |
| </td> |
| <td style="vertical-align: top;">128<br> |
| </td> |
| <td style="vertical-align: top;">blocks_per_transfer (granularity |
| of each IO)<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">cdbsz=6|10|12|16<br> |
| </td> |
| <td style="vertical-align: top;">10 or 16<br> |
| </td> |
| <td style="vertical-align: top;">cdb size of SCSI READ and/or |
| WRITE commands<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">coe=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">continue_on_error when set<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">dio=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">direct IO (only via sg device |
| nodes)<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">fua=0|1|2|3<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">force_unit_access, 1->if, |
| 2->of, 3->if+of<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">odir=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">O_DIRECT flag on open() when set<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">sync=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">SYNCHRONIZE CACHE SCSI command |
| after transfer when set<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">time=0|1<br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">when set print elapsed time and |
| throughput after copy<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">verbose=<n><br> |
| </td> |
| <td style="vertical-align: top;">0<br> |
| </td> |
| <td style="vertical-align: top;">larger <n> is the greater |
| the debug output<br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">--version<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| <td style="vertical-align: top;">print the version number and |
| release date of |
| sg_dd then exit<br> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <br> |
| <br> |
| The sg_dd utility examines the files it is given and treats them |
| differently depending on the category and, in some case,s the command |
| line options given:<br> |
| <br> |
| <table style="width: 100%; text-align: left;" border="1" cellpadding="2" |
| cellspacing="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">File |
| type</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">open |
| [when input]</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">open |
| [when output]</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">IO |
| method</span><br> |
| </td> |
| <td style="vertical-align: top;"><span style="font-weight: bold;">Notes</span><br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">normal<br> |
| </td> |
| <td style="vertical-align: top;">O_RDONLY<br> |
| <br> |
| </td> |
| <td style="vertical-align: top;">O_WRONLY | O_CREAT<br> |
| [add O_APPEND if 'append=1']<br> |
| </td> |
| <td style="vertical-align: top;">Unix read() write()<br> |
| </td> |
| <td style="vertical-align: top;">Add O_DIRECT if<br> |
| 'odir=1'<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">stdin or stdout<br> |
| </td> |
| <td style="vertical-align: top;">[do nothing]<br> |
| </td> |
| <td style="vertical-align: top;">[do nothing]<br> |
| </td> |
| <td style="vertical-align: top;">Unix read() write()<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">/dev/null<br> |
| </td> |
| <td style="vertical-align: top;">O_RDONLY</td> |
| <td style="vertical-align: top;">[do nothing]<br> |
| </td> |
| <td style="vertical-align: top;">Unix read() if input<br> |
| </td> |
| <td style="vertical-align: top;">if output then no IO<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">block device<br> |
| </td> |
| <td style="vertical-align: top;">O_RDONLY</td> |
| <td style="vertical-align: top;">O_WRONLY | O_CREAT<br> |
| [add O_APPEND if 'append=1']</td> |
| <td style="vertical-align: top;">Unix read() write()</td> |
| <td style="vertical-align: top;">Add O_DIRECT if<br> |
| 'odir=1'</td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">block device [blk_sgio=1]<br> |
| </td> |
| <td style="vertical-align: top;">O_RDWR or O_RDONLY</td> |
| <td style="vertical-align: top;">O_RDWR</td> |
| <td style="vertical-align: top;">SCSI commands</td> |
| <td style="vertical-align: top;">Opens input O_RDONLY <br> |
| if O_RDWR fails. Adds <br> |
| O_DIRECT if 'odir=1' </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">sg device<br> |
| </td> |
| <td style="vertical-align: top;">O_RDWR or O_RDONLY<br> |
| </td> |
| <td style="vertical-align: top;">O_RDWR<br> |
| </td> |
| <td style="vertical-align: top;">SCSI commands<br> |
| </td> |
| <td style="vertical-align: top;">Opens input O_RDONLY<br> |
| if O_RDWR fails</td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">raw device<br> |
| </td> |
| <td style="vertical-align: top;">O_RDONLY</td> |
| <td style="vertical-align: top;">O_WRONLY<br> |
| </td> |
| <td style="vertical-align: top;">Unix read() write()<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">scsi tape device<br> |
| </td> |
| <td style="vertical-align: top;">x<br> |
| </td> |
| <td style="vertical-align: top;">x<br> |
| </td> |
| <td style="vertical-align: top;">no IO<br> |
| </td> |
| <td style="vertical-align: top;">error reported<br> |
| </td> |
| <td style="vertical-align: top;"><br> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <br> |
| Some of the above combinations are not sensible (e.g. 'append=1' on a |
| block device). Raw devices were introduced in the lk 2.4 series and are |
| still available in the lk 2.6 series but opening a block device or a |
| normal file with O_DIRECT (in sg_dd using the option 'odir=1') is |
| preferred.<br> |
| <br> |
| The 'blk_sgio=1' option is only valid in the lk 2.6 series. This option |
| instructs the sg_dd utility to use the SG_IO ioctl to issue SCSI |
| commands even though the file type is not a scsi generic (sg) device. |
| Currently this will work for all cd/dvd devices irrespective of the |
| transport (except for some very old devices ( > 10 years old)) and |
| block devices representing SCSI disks (e.g. /dev/sda). Even though SCSI |
| tape (st) devices now accept the SG_IO ioctl in the lk 2.6 series, the |
| sg_dd utility expects direct access devices (whereas tapes are |
| sequential access) so sg_dd generates an error if a st device is |
| detected. When the input or output file is a sg device then the |
| 'blk_sgio' option is ignored as IO with that file is always via SCSI |
| commands.<br> |
| <br> |
| If a partition of block device is accessed (e.g. /dev/sda2) when |
| 'blk_sgio=0' (or is not given) then logical block address 0 for the |
| purposes of sg_dd (and its skip and seek options) is the beginning of |
| that partition while the calculated count (e.g. when a 'count' option |
| is not given) is the extent of that partition. However if a partition |
| of block device is accessed (e.g. /dev/sda2) when 'blk_sgio=1' then the |
| partition is ignored and the underlying device is accessed. This means |
| logical block address 0 for the purposes of sg_dd (and its skip and |
| seek options) is the beginning of the device while the calculated count |
| (e.g. when a 'count' option is not given) is the extent of that device.<br> |
| <br> |
| Note about CDs and count (perhaps DVDs don't have this problem). When a |
| CD is accessed via SCSI commands and the 'count' option is not given |
| then the READ CAPACITY SCSI command is used by sg_dd to determine the |
| number of blocks to read. Unfortunately some MMC standards allow a few |
| of the final blocks to be invalid ("run out" sectors) and this can |
| result in IO errors when the sg_dd utility is used to copy such a CD. |
| The isosize utility can be used to determine the actual size of an |
| ISO9660 file system residing on such a CD. It is often a few blocks |
| shorter than READ CAPACITY reports (for good reason).<br> |
| <br> |
| When an input or output file is being accessed via SCSI commands the |
| following "extra" options being discussed in this section are active:<br> |
| <ul> |
| <li>bpt: each cdb issued will be for this value or less blocks (with |
| the block size implied)<br> |
| </li> |
| <li>cdbsz: defaults to a 10 byte cdb if IO fits in 32 bit lba space |
| otherwise 16 byte cdb</li> |
| <li>coe: when set error on read get special treatment (see below)</li> |
| <li>dio: only active for sg devices (i.e. not block device with |
| 'blk_sgio=1')</li> |
| <li>fua: force_unit_access flag in cdb; 1->if, 2->of; |
| 3->if+of</li> |
| <li>odir: active when file is a block device (i.e. inactive for sg |
| devices)<br> |
| </li> |
| <li>sync: when set issues SYNCHRONIZE CACHE command at the end of the |
| copy</li> |
| <li>time</li> |
| <li>verbose: 1 and 2 print setup cdbs, 3 and 4 print all cdbs</li> |
| </ul> |
| When an input or output file is being accessed via normal Unix read() |
| and write() commands the following "extra" options being discussed in |
| this section are active:<br> |
| <ul> |
| <li>append: one active on output file that are "normal" (i.e. neither |
| devices nor streams)<br> |
| </li> |
| <li>bpt: each IO operation transfers (bs * bpt) bytes or less</li> |
| <li>odir: opens files with the O_DIRECT flag</li> |
| <li>time</li> |
| <li>verbose: 1 + 2 print setup system calls, 3 and 4 additional print |
| read() and write() system calls<br> |
| </li> |
| </ul> |
| If a SIGUSR1 signal is sent to the process identifier (pid) of a |
| running sg_dd utility then the number of blocks copies to that point is |
| output. The copy continues.<br> |
| <br> |
| When the 'time' option is set, the elapsed time for the copy plus the |
| throughput measured in megabytes (10**6 bytes) per second is |
| output when the copy is complete (or an error stops the copy). If a |
| SIGUSR1 signal is sent to the process identifier (pid) of a running |
| sg_dd utility which has the 'time' option set the elapsed time and the |
| throughput of the copy to that point is output and the copy continues.<br> |
| <h2><a name="coe"></a>Continue on error (coe)</h2> |
| Recent additions to the sg_dd utility allow it to be used as a copy "of |
| last resort" from failing media. Read errors on an input file |
| taking SCSI commands are "tolerated" when the 'coe' option is set. |
| Write errors from SCSI commands are reported and ignored and the sg_dd |
| utility continues when the 'coe' option is set. [In the case where |
| media errors are causing write errors the |
| reader should check the setting of the AWRE bit in the SCSI "read write |
| error recovery" mode page (see SBC-2 at http://www.t10.org).] As for |
| errors in normal files the reader may wish to examine the |
| "conv=noerror" option of the dd command.<br> |
| <br> |
| When a SCSI READ command detects an unrecoverable read error it |
| responds with a sense key of MEDIUM ERROR or HARDWARE ERROR. |
| Additionally it responds with the logical block address of the first |
| (lowest) block that it failed to read in the current READ command. Any |
| valid blocks prior to the "bad" block may or may not have been |
| transferred (depending on several other settings). If 'coe=0' then the |
| sg_dd utility will simply terminate at this point (with a reasonable |
| amount of debug information sent to stderr). If 'coe=1' then the first |
| thing it will try to do is a truncated read up to but not including the |
| bad block. The remaining discussion in this section assumes 'coe=1'.<br> |
| <br> |
| The "bad" block may or may not be readable by the device. If it is |
| readable then most likely the associated ECC data indicates that it is |
| corrupt and the ECC data cannot recover it. [It is possible that all |
| the corruption is in the ECC data and the payload data is ok.] Such |
| blocks can be retrieved with the READ LONG command which is what the |
| sg_dd utility does. If the READ LONG fails then a block of zeroes is |
| substituted for the bad block in the transfer buffer. Only SBC-2 |
| devices (primarily SCSI disks) optionally support READ LONG. CD/DVD |
| devices (covered in the MMC-4 (draft) standard) do not so a block of |
| zeroes is substituted for them.<br> |
| <br> |
| There still remains blocks after the "bad" block in the initial |
| transfer to be fetched. Further bad blocks may be detected and if so |
| the algorithm in the last two paragraph is repeated. The result of this |
| process is an imperfect copy with blocks that were read properly placed |
| in the correct relative position in the output. When the 'coe=1' option |
| is given two addition counters are output on completion:<br> |
| <ul> |
| <li>unrecovered errors</li> |
| <li>read_longs fetched part of unrecovered read errors</li> |
| </ul> |
| The first counter is the number of unrecovered (read) errors |
| encountered. Any number greater than zero flags an imperfect copy. The |
| second counter (always less than or equal to the first) is the number |
| of "successful" READ LONG SCSI commands performed. If the source media |
| is a CD or DVD then this number will be zero.<br> |
| <br> |
| <h2><a name="Recovered_errors"></a>Recovered errors</h2> |
| Often errors are recovered using ECC data or by the device retrying |
| (usually re-reading) the media. Also at the first sign of trouble, |
| recoverable errors lead to the block in question being reassigned to |
| another location on the media (automatically when the AWRE and ARRE |
| bits are set in the "read write error recovery" mode page). The |
| user of such a disk may be blissfully unaware that the disk may be |
| reaching the end of its useful life. Error counters are maintained in |
| the "Read error counter" and "Write error counter" logs pages which can |
| be viewed with smartctl (from smartmontools) and sg_logs (from the same |
| sg3_utils package that sg_dd comes from). Any block that is |
| automatically or manually re-assigned add a new entry to the "grown" |
| defect list which cal be viewed with 'sginfo -G' (also found in the |
| sg3_utils package).<br> |
| <br> |
| A disk can be instructed to report RECOVERED ERRORs by setting the PER |
| bit in the "read write error recover" mode page. Most often this bit is |
| clear. When sg_dd detects RECOVERED ERRORs it reports them, counts |
| them and continues the copy. Only the lba of the last recovered error |
| in a READ or WRITE SCSI |
| command is reported so there could be more than one recovered error per |
| SCSI command. The 'bpt=1' option |
| could be chosen to limit every SCSI command to a single block transfer |
| (but that would slow things down a fair amount). If the count of |
| recovered errors is greater than zero at the end of the copy then this |
| count is output as well.<br> |
| <br> |
| There can be other reasons for a sense key of RECOVERED ERROR not |
| directly related to data being currently read or written. SMART alerts |
| (called in SCSI documents "Informational Exceptions") can be conveyed |
| via a RECOVERED ERROR sense key (see the MRIE field in the |
| Informational Exceptions mode page). Such alerts have additional sense |
| codes like "Failure prediction threshold exceeded" and those that |
| contain "impending failure".<br> |
| <h2><a name="Verbose"></a>Verbose</h2> |
| In the Unix style, sg_dd doesn't output anything (to stderr) during |
| large IO transfers. To get a progress report the SIGUSR1 signal can be |
| sent to the sg_dd process. In the Unix dd command style, sg_dd outputs |
| two lines on completion that show the number of full and partial |
| records |
| in (on the first line) and out (on the second line). Some modern |
| versions of the dd command also output elapsed time and throughput |
| figures (to get this with sg_dd use the "time=1" option).<br> |
| <br> |
| The sg_dd has a 'verbose' option whose default value is zero. When set |
| this option has the following actions:<br> |
| <ol> |
| <li>show categorization and INQUIRY data (where applicable) for the |
| input and output files. For files, other than streams, the file/device |
| size (and device block size) are output. For SCSI devices mode data |
| relevant to error recovery and caching is output.</li> |
| <li>same output as 1 plus data for Unix and SCSI commands (cdbs) that |
| are not repeated (i.e. other than Unix read/write and SCSI READ/WRITE |
| commands). Increased error reporting for all SCSI commands</li> |
| <li>same output as 2 plus data for Unix and SCSI commands (cdbs) that |
| are repeated. For a large copy this will be a lot of output.</li> |
| <li>maximum amount of debug output. For a large copy this will be a |
| lot of output.</li> |
| </ol> |
| All verbose output is sent to stderr (so that sg_dd usage with "of=-" |
| (copy output to stdout) is not corrupted).<br> |
| <br> |
| Following is an example of using "verbose=1" to find information about |
| /dev/sda . If no copy is required then setting "count=0" will see to |
| that. Since "dev/sda" is a block device then it would normally be |
| accessed via Unix system commands. The "verbose=1" output is relatively |
| short when "blk_sgio=0" (its default value). The second invocation is |
| with "blk_sgio=1" and a lot more is output. That includes INQUIRY |
| standard response data (e.g. "SEAGATE ..." line) followed by the |
| setting of various mode pages relevant to error processing and caching. |
| See the SBC-2 drafts at <a href="http://www.t10.org/">www.t10.org</a> |
| for more information. As an example a AWRE bit of 1 means that the disk |
| will automatically reallocate a logical block address (to another |
| sector) |
| if a recoverable error is detected on a WRITE operation. RECOVERED |
| ERRORs are only report on read and write operations when the PER [Post |
| Error] bit is set.<br> |
| <br> |
| <span style="font-family: monospace;">$ sg_dd if=/dev/sda of=. bs=512 |
| verbose=1 count=0 blk_sgio=0</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> >> Input file type: |
| block device</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| open input, flags=0x0</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> >> Output file type: |
| null device</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| [bgs64] number of blocks=17781521 [0x10f5311], block size=512</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;">0+0 records in</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;">0+0 records out</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"><br> |
| <br> |
| $ sg_dd if=/dev/sda of=. bs=512 verbose=1 count=0 blk_sgio=1</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> >> Input file type: |
| block device</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| open input(sg_io), flags=0x2</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> /dev/sda: |
| SEAGATE |
| ST39173LC 1234 |
| [pdt=0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> Read write error recovery |
| mode page:</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| AWRE: 1 [Changeable: y, def: 1, |
| saved: 1]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| ARRE: 1 [Changeable: y, def: 1, |
| saved: 1]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| RC: 0 [Changeable: y, |
| def: 0, saved: 0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| EER: 1 [Changeable: y, def: |
| 0, saved: 1]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| PER: 1 [Changeable: y, def: |
| 0, saved: 1]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| DTE: 0 [Changeable: y, def: |
| 0, saved: 0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| DCR: 0 [Changeable: y, def: |
| 0, saved: 0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> Caching mode page:</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| WRE: 1 [Changeable: y, def: |
| 1, saved: 1]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| RCD: 0 [Changeable: y, def: |
| 0, saved: 0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> Control mode page:</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| SWP: 0 [Changeable: n, def: |
| 0, saved: 0]</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> >> Output file type: |
| null device</span><br style="font-family: monospace;"> |
| <span style="font-family: monospace;"> |
| number of blocks=17781521 [0x10f5311], block size=512</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;">0+0 records in</span><br |
| style="font-family: monospace;"> |
| <span style="font-family: monospace;">0+0 records out</span><br> |
| <br> |
| Some of the output above is out of order, the "number of blocks" line |
| relates to the input file.<br> |
| <h2><a name="Conclusion"></a>Conclusion</h2> |
| The sg_dd utility maintains syntactic and semantic compatibility with |
| the Unix dd command while allowing precise control over SCSI devices |
| such as SCSI disks and CD/DVD drives. Amongst other uses it can copy |
| data from failing media, continuing as best it can when medium errors |
| are encountered.<br> |
| <br> |
| <br> |
| <p>Return to <a href="index.html">main</a> page. </p> |
| <center> |
| <p>Last updated: 14th March 2005<br> |
| <br> |
| </p> |
| </center> |
| </body> |
| </html> |