SG_WRITE_SAME(8)
π SG_WRITE_SAME(8) Β· SG3_UTILS π
β¨ NAME β¨
sg_write_same - send SCSI WRITE SAME command π
π§ SYNOPSIS π§
sg_write_same [--10] [--16] [--32] [--anchor] [--ff] [--grpnum=GN]
[--help] [--in=IF] [--lba=LBA] [--lbdata] [--num=NUM] [--ndob]
[--pbdata] [--timeout=TO] [--unmap] [--verbose] [--version]
[--wrprotect=WPR] [--xferlen=LEN] DEVICE
π DESCRIPTION π
okay so this utility sends the SCSI WRITE SAME (10, 16 or 32 byte) command to DEVICE β¨ It writes the given block NUM times to consecutive blocks on the DEVICE, starting at logical block address LBA π¦
the size of the block you're repeating comes from one of three places: the LEN argument, the length of the input file IF, or a READ CAPACITY(16) call on DEVICE π₯ the contents come from the input file IF, or you get zeros if you don't give one π«Ά if READ CAPACITY(16) gets called (which means IF was not given) and the PROT_EN bit is set, then an extra 8 bytes (i.e. more than the logical block size) of 0xff get sent too π and if READ CAPACITY(16) fails, READ CAPACITY(10) steps in to figure out the block size π
if you don't give --10, --16 or --32, WRITE SAME(10) is sent by default πΈ unless one of these is true: LBA (plus NUM) goes past 32 bits, NUM is bigger than 65535, or you gave the --unmap option. in any of those cases, WRITE SAME(16) is sent instead π also, --10, --16 and --32 are mutually exclusive, so pick one bestie π
SBC-3 revision 35d introduced a "No Data-Out Buffer" (NDOB) bit π when it's set, you skip the requirement to send a single block of data to the DEVICE along with the command β¨ only WRITE SAME (16 and 32 byte) support the NDOB bit π if you give it, a user block of zeros is assumed, and if protection information is required, 0xffs are assumed π
in SBC-3 revision 26, the UNMAP and ANCHOR bits were added to the WRITE SAME (10) command π the UNMAP bit has been in WRITE SAME (16) and WRITE SAME (32) since SBC-3 revision 18, so the lower of the two (i.e. WRITE SAME (16)) is the default when you use --unmap π if you actually want WRITE SAME (10), use the --10 option π¦
π Take care, bestie: the WRITE SAME(10, 16 and 32) commands may interpret a NUM of zero as "write to the end of DEVICE" π¨ this utility defaults NUM to 1 . the WRITE SAME commands have no IMMED bit, so if NUM is large (or zero), an invocation of this utility could take a long time, potentially as long as a FORMAT UNIT command π in those situations you may need to bump up the command timeout value TO from its default of 60 seconds β°
in SBC-3 revision 26, the WSNZ (write same no zero) bit was added to the Block Limits VPD page [0xB0] πΈ if it's set, the WRITE SAME commands will not accept a NUM of zero π ββοΈ that same revision also added the "Maximum Write Same Length" field to the Block Limits VPD page π
the Logical Block Provisioning VPD page [0xB2] has the LBPWS and LBPWS10 bits π§ if LBPWS is set, WRITE SAME (16) supports the UNMAP bit π if LBPWS10 is set, WRITE SAME (10) supports the UNMAP bit β¨ and if either LBPWS or LBPWS10 is set and WRITE SAME (32) is supported, then WRITE SAME (32) supports the UNMAP bit too π¦
as a precaution against an accidental sg_write_same /dev/sda (for example) overwriting LBA 0 on /dev/sda with zeros π± you have to give at least one of the --in=IF, --lba=LBA or --num=NUM options π‘οΈ obviously this utility can destroy a lot of user data, so check your options carefully, periodt π«Ά
π OPTIONS π
arguments to long options are mandatory for short options as well π the options are arranged in alphabetical order based on the long option name β¨
-R,--10β send a SCSI WRITE SAME (10) command to DEVICE π the ability to set the--unmap(and--anchor) options on this command was added in SBC-3 revision 26 πΈ-S,--16β send a SCSI WRITE SAME (16) command to DEVICE π¦-T,--32β send a SCSI WRITE SAME (32) command to DEVICE π₯-a,--anchorβ sets the ANCHOR bit in the cdb π§ introduced in SBC-3 revision 22 π that draft requires the--unmapoption to also be specified, so don't forget it bestie π-f,--ffβ the data-out buffer sent with this command gets initialized with0xffbytes when you give this option π
Okay so the UNMAP option is literally the main character of this whole page π Let's get into it bestie π«Ά
Logical block provisioning is a newer term from SBC-3 revision 25 πΈ It's the ability to mark blocks as unused. For big storage arrays, that means you can provision less physical storage than what the READ CAPACITY command says is available, and then allocate more physical storage later when WRITE commands actually need it. π§ For flash memory (like SSD drives), it can potentially save power (and maybe access time) when huge chunks of the flash, or almost all of it, aren't in use. SSDs need wear levelling algorithms to have acceptable endurance, and they usually over provision to make those algorithms simpler π₯ So they often have more physical flash than their logical size would suggest. Iconic engineering, honestly π
Support for logical block provisioning shows up as the LBPME bit being set in the READ CAPACITY(16) command response (check out the sg_readcap utility for that) β¨ That implies at least one of the UNMAP or WRITE SAME(16) commands is implemented. If the UNMAP command is implemented, then the "Maximum unmap LBA count" and "Maximum unmap block descriptor count" fields in the Block Limits VPD page should both be greater than zero π The READ CAPACITY(16) response also has an LBPRZ bit. If it's set, reading unmapped blocks gives you zeros back for the data (and if protection information is active, you get 0xff bytes back for that part instead) π¦ In SBC-3 revision 27, that same LBPRZ bit got added to the Logical Block Provisioning VPD page too, so it's giving consistency π
In SBC-3 revision 25, the LBPU and ANC_SUP bits were added to the Logical Block Provisioning VPD page π When LBPU is set, the device supports the UNMAP command (see the sg_unmap utility). When ANC_SUP is set, the device supports anchored LBAs.
When the UNMAP bit is set in the cdb, the data-out buffer is also sent π The data section of that data-out buffer should be full of 0x0 bytes, while the data protection block (8 bytes at the end, if present) should be set to 0xff bytes. If those conditions aren't met and the LBPRZ bit is set, then the UNMAP bit gets ignored and the data-out buffer is written to the DEVICE as if the UNMAP bit was zero. Without the --in=IF option, this utility will try to build a data-out buffer that meets the UNMAP bit requirements in the cdb, so it can be acted on by the DEVICE π
Logical blocks can also be unmapped by the SCSI UNMAP and FORMAT UNIT commands (see the sg_unmap and sg_format utilities) π
The unmap capability in SCSI is closely related to the ATA DATA SET MANAGEMENT command with the "Trim" bit set π§ That ATA trim capability doesn't play nicely with SATA command queueing, which is known as NCQ π T13 introduced a new command called the SFQ DATA SET MANAGEMENT command, also with a "Trim" bit, to fix that problem β¨ The SCSI WRITE SAME with the UNMAP bit set, and the UNMAP commands, don't have any problems with SCSI queueing. No notes, just vibes π
πΈ NOTES πΈ
Various numeric arguments (e.g. LBA) can include multiplicative suffixes or be given in hexadecimal π’ See the "NUMERIC ARGUMENTS" section in the sg3_utils(8) man page π
In Linux, prior to lk 3.17, the sg driver didn't support cdb sizes greater than 16 bytes π So a device node like /dev/sg1, which is associated with the sg driver, would fail with this utility if the --32 option was given (or implied by other options). The bsg driver, with device nodes like /dev/bsg/6:0:0:1, does support cdb sizes greater than 16 bytes, ever since it was introduced in lk 2.6.28 . Main character energy from bsg π¦
π EXIT STATUS π
The exit status of sg_write_same is 0 when it's successful π«Ά Otherwise, check out the sg3_utils(8) man page.
π₯ EXAMPLES π₯
BEWARE π¨ All these examples will overwrite the data on one or more blocks, potentially CLEARING the WHOLE DISK. Bestie, I'm serious π
One simple usage is writing blocks of zero from (and including) a given LBA, for 63 blocks π
sg_write_same --lba=0x1234 --num=63 /dev/sdc
Since --xferlen=LEN hasn't been given, this utility will call the READ CAPACITY command on /dev/sdc to figure out how many bytes are in a logical block. Let's assume that's 512 bytes. Since --in=IF isn't given, a block of zeros is assumed. So 63 blocks of zeros (each block containing 512 bytes) get written from (and including) LBA 0x1234 . Note that only one block of zeros is passed to the SCSI WRITE SAME command in the data-out buffer (as required by SBC-3) π§ Using the WRITE SAME SCSI command to write one or more blocks of zeros is equivalent to the NVMe command: Write Zeroes β¨
Now we're going to write zero blocks to the WHOLE disk π«£ [Note: sanitize type commands will also clear blocks and metadata that aren't directly visible]
sg_write_same --lba=0x0 --num=0 /dev/sdc
Yes, in this context --num=0 means the rest of the disk π
The invocation above may give an error because the WSNZ bit in the Block Limits VPD page is set. To get around that, try:
sg_write_same --lba=0x0 --ndob /dev/sdc
This invocation, if it's supported, has the added benefit of not sending a data-out buffer of zeros π Just note that the "provisioning initialization pattern" might get written to each block instead of zeros π
A similar example follows, but this time the blocks are "unmapped" ("trimmed" in ATA speak) instead of zeroed π¦
sg_write_same --unmap -L 0x1234 -n 63 /dev/sdc
If the LBPRZ bit in the READ CAPACITY(16) response is set (i.e. LPPRZ is an acronym for logical block provisioning read zeros), then these two examples do the same thing, at least from the point of view of subsequent reads π
This utility can also write protection information (PI) on disks formatted with a protection type greater than zero π PI is 8 bytes of extra data appended to the user data of a logical block. The first two bytes are a CRC (the "guard"), the next two bytes are the "application tag", and the last four bytes are the "reference tag" π With protection types 1 and 2, if the application tag is 0xffff, then the guard should not be checked (against the user data) β¨
In this example, we assume the logical block size (of the user data) is 512 bytes, and the disk has been formatted with protection type 1. Since we're going to modify LBA 2468, we take a copy of it first π«Ά
dd if=/dev/sdb skip=2468 bs=512 of=2468.bin count=1
The following command line sets the user data to zeros and the PI to 8 0xFF bytes on LBA 2468 π
sg_write_same --lba=2468 /dev/sdb
Reading back that block should succeed, because the application tag is 0xffff, which suppresses the guard (CRC) check (which would otherwise be wrong) π
dd if=/dev/sdb skip=2468 bs=512 of=/dev/null count=1
Now let's make a binary file with zeros in the user data, 0x0000 in the application tag, and 0xff bytes in the other two PI fields. It's awkward to create 0xff bytes in a file (in Unix), as the "tr" command below shows π
dd if=/dev/zero bs=1 count=512 of=ud.bin
tr "\000" "\377" < /dev/zero | dd bs=1 of=ff_s.bin count=8
cat ud.bin ff_s.bin > lb.bin
dd if=/dev/zero bs=1 count=2 seek=514 conv=notrunc of=lb.bin
The resulting file can be viewed with hexdump -C lb.bin and should contain 520 bytes π§ Now that file can be written to LBA 2468 like this:
sg_write_same --lba=2468 wrprotect=3 --in=lb.bin /dev/sdb
Note the --wrprotect=3 rather than 1, since we want the WRITE SAME command to succeed even though the PI data now indicates the user data is corrupted π When an attempt is made to read that LBA, an error should occur:
dd if=/dev/sdb skip=2468 bs=512 of=/dev/null count=1
dd errors aren't very expressive π If you check dmesg, there should be a line something like this: "[sdb] Add. Sense: Logical block guard check failed". The block can be corrected by running sg_write_same --lba=1234 /dev/sdb again, or by restoring the original contents of that LBA:
dd if=2468.bin bs=512 seek=2468 of=/dev/sdb conv=notrunc count=1
Hopefully the dd command would never try to truncate the output file when it's a block device π
π§ AUTHORS π§
Written by Douglas Gilbert π
π REPORTING BUGS π
Report bugs to <dgilbert at interlog dot com> π«Ά
βοΈ COPYRIGHT βοΈ
Copyright Β© 2009-2020 Douglas Gilbert This software is distributed under a BSD-2-Clause license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE πΈ
π SEE ALSO π
sg_format, sg_get_lba_status, sg_readcap, sg_vpd, sg_unmap, sg_write_x(sg3_utils) π¦
That's a wrap, bestie π This was sg3_utils 1.45 from June 2020, and the SG_WRITE_SAME(8) page is officially iconic πβ¨ Now go write some zeros responsibly π π
π¦ where this page comes from
- alpine 3.24: sg3_utils-doc 1.48-r0 Β· BSD-2-Clause AND GPL-2.0-or-later
- arch rolling: sg3_utils 1.49-1 Β· GPL-2.0-or-later AND BSD-2-Clause
- centos-stream 10: sg3_utils 1.48-11.el10 Β· GPL-2.0-or-later AND BSD-2-Clause
- debian trixie: sg3-utils 1.48-3~deb13u1
- fedora 43: sg3_utils 1.48-10.fc43 Β· GPL-2.0-or-later AND BSD-2-Clause
- fedora 43: sg3_utils 1.48-6.fc43 Β· GPL-2.0-or-later AND BSD-2-Clause
- fedora 44: sg3_utils 1.48-10.fc44 Β· GPL-2.0-or-later AND BSD-2-Clause
- fedora 44: sg3_utils 1.48-8.fc44 Β· GPL-2.0-or-later AND BSD-2-Clause
- nixos 26.05: sg3_utils 1.48
- nixpkgs unstable: sg3_utils 1.49
- ubuntu questing: sg3-utils 1.48-2ubuntu1
- ubuntu resolute: sg3-utils 1.48-3ubuntu3
- ubuntu resolute: sg3-utils 1.48-3ubuntu3.2
- ubuntu stonking: sg3-utils 1.48-3ubuntu5
- π girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms