sg_unmap tells a SCSI device that ranges of logical blocks are no longer needed, and a wrong range can discard live data. This guide builds the request, dry-runs it, and forces a deliberate pause before anything is actually discarded.
Allow about fifteen minutes, plus time to confirm that the device and its backups are correct. The examples use the installed sg_unmap from sg3-utils package version 1.46-3ubuntu4; the utility itself reports version 1.17 from 28 June 2018.
UNMAP is related to ATA TRIM, but it is not a file deletion tool and it does not make a filesystem safe to use while it is mounted. Treat every command that sends UNMAP as destructive.
Start with read-only checks. These do not need elevated privileges unless your system hides the device or package database from your account:
$ command -v sg_unmap
/usr/bin/sg_unmap
$ sg_unmap --version
version: 1.17 20180628
$ dpkg-query -W sg3-utils
sg3-utils 1.46-3ubuntu4
The device argument is normally a SCSI generic path such as /dev/sg2. Do not substitute a path merely because it exists. Identify the correct device from your storage inventory, multipath configuration, or the output of the SCSI tools used on your host.
Logical block provisioning is advertised by the device. Use sg_readcap to inspect capacity information and sg_vpd to inspect the relevant VPD page. These are ordinary read-only commands:
$ sg_readcap --long /dev/sg2
$ sg_vpd --page=bl /dev/sg2
The sg_unmap manual describes support through the LBPME bit in READ CAPACITY (16), and through the LBPU bit in the Logical Block Provisioning VPD page. You need a device that advertises UNMAP support. If the commands fail, or the device does not advertise it, stop there. Do not add --force to work around a capability or access error.
Use elevated privileges only when your device permissions require them. A read-only check with sudo may look like this:
$ sudo sg_readcap --long /dev/sg2
$ sudo sg_vpd --page=bl /dev/sg2
Checkpoint: Write down the exact device path and the reason for unmapping it. A storage enclosure can expose several similar-looking paths, and guessing is not a recovery strategy.
For separate ranges, pair each starting LBA with its number of blocks. This example requests 256 blocks starting at LBA 8192, then 128 blocks starting at LBA 20000:
$ sg_unmap --lba=8192,20000 --num=256,128 --dry-run /dev/sg2
--lba and --num must contain the same number of values.0x or add a trailing h for hexadecimal.$ sg_unmap --lba='0x2000 0x4e20' --num='0x100 0x80' --dry-run /dev/sg2
The dry run opens the device, sends a standard INQUIRY, and may perform the preparation needed for the request, but exits before sending UNMAP commands. It is a useful syntax and access check, not proof that the final request is harmless. Check its exit status:
$ printf 'dry-run exit status: %s\n' "$?"
dry-run exit status: 0
If you see a list-count error, compare the two lists. If the device opens but preparation fails, keep the diagnostic and resolve that problem before attempting a real request.
An input file is easier to review when a request contains several ranges. Each pair is a starting LBA followed by the number of logical blocks. Blank lines and text from # to the end of a line are ignored:
# lba number of blocks
8192 256
20000 128
0x30000 1k
Save that content as unmap-ranges.txt, then run the dry run:
$ sg_unmap --in=unmap-ranges.txt --dry-run /dev/sg2
Do not combine --in with --lba. The file must contain an even number of values, and one line must not exceed 1023 bytes. The utility accepts up to 128 LBA and count pairs, although the device can impose a lower maximum through its Block Limits VPD page.
Review the file as data, not as a shell script. It is parsed by sg_unmap, so command substitutions and shell quoting do nothing useful inside it. Keep a copy with the change record for the device and the filesystem or application that produced the ranges.
When the device path, support checks, ranges and backup position have all been verified, run the same request without --dry-run:
$ sudo sg_unmap --in=unmap-ranges.txt /dev/sg2
Without --force, the installed utility waits 15 seconds and displays a warning before sending UNMAP. Use that pause as the final opportunity to press Control-C. The command may issue more than one UNMAP when a large request is split into batches.
Warning: Do not use --force interactively unless the request has already passed an equivalent review. It removes the cooling-off period. It is intended for a controlled batch job, not for making an uncertain command feel faster.
A successful command exits with status 0. The operation has no general undo command: UNMAP changes the device's provisioning state, and any recovery depends on the device, its snapshots and your backups.
After a successful request, use the device's provisioning and allocation reporting tools to check its state where supported. sg_get_lba_status can report logical block status, but its output is device-dependent:
$ sudo sg_get_lba_status /dev/sg2
$ printf 'sg_unmap exit status: %s\n' "$?"
sg_unmap exit status: 0
Do not interpret a zero exit status as proof that an application can immediately reuse every block. The command reports that the SCSI operation completed; filesystem allocation, thin-provisioning policy and device reclamation are separate layers.
A timeout is configurable with --timeout=SECONDS, whose default is 60 seconds. Increase it only when the device documentation and observed workload justify doing so. A timeout change does not make an unsupported or incorrect range safe. If you need to unmap an entire logical unit, read the manual's warning and consider whether the device's FORMAT UNIT workflow is the appropriate operation instead.
If the command fails, preserve its diagnostic and exit status, do not immediately retry with --force, and confirm that no partial request was completed before retrying. Ask the storage vendor or administrator about the device's UNMAP limits if the ranges exceed its advertised maximum.
--dry-run before any UNMAP command was sent.--force.