Safely Reassign SCSI Blocks with sg_reassign
sg_reassign tells a SCSI drive to swap a failing block for a spare one. You will inspect the defect lists, rehearse the reassignment as a dummy run, then send the one live command that actually changes anything, which is deliberately irreversible. Budget about fifteen minutes for a known device and one or two block addresses, longer if you are chasing a failing disk.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide is checked against sg3-utils 1.46-3ubuntu4. The binary reports itself as sg3_utils version 1.27, dated 1 October 2019, while the local manual page is for sg3_utils 1.45. Small version drift is normal, so check your own command and manual before touching a production device.
1. Confirm the device and command
Start read-only. You need the sg3-utils package and a SCSI block device you have positively identified. An ordinary shell handles all three checks:
$ command -v sg_reassign
/usr/bin/sg_reassign
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_reassign --version
version: 1.27 20191001
Use a stable path such as /dev/disk/by-id/ instead of copying a /dev/sdX name out of an old incident report: it can point somewhere else after the next reboot. Confirm the identity with your normal SCSI or inventory tools. If you cannot say which physical disk the path names, stop.
Checkpoint
Write down the exact device path and the logical block address you are investigating. A logical block address is not a byte offset, and must not be converted by guessing the sector size.
2. Inspect the grown defect list
The safest first move is --grown. It sends a SCSI READ DEFECT DATA (10) command and reports how many entries sit in the grown defect list, commonly called the GLIST, without reassigning anything:
$ sg_reassign --grown /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
<device-dependent defect-list count and status>
Wording and count are device-dependent, so treat the output as a report to log, not a fixed transcript. A non-zero count is a health signal, not proof that every listed block is currently unusable. If the list is climbing fast, sort out backups, error logs, self-tests and replacement planning before trying to consume more spare locations.
Add --hex to --grown for a hexadecimal dump when you need it for troubleshooting. --primary queries the manufacturing-time primary defect list, or PLIST, instead:
$ sg_reassign --primary /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
$ sg_reassign --hex --grown /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
--grown and --primary are passive query modes only. They cannot be combined with --address, because that pairing selects READ DEFECT DATA rather than REASSIGN BLOCKS.
3. Rehearse the reassignment before sending it
Warning
REASSIGN BLOCKS changes the device's defect management state. The operation is essentially irreversible, and it draws on a limited pool of vendor-provided spare locations. Do not use a throwaway address as a test.
Pass one or more logical block addresses with --address. Numbers are decimal unless prefixed with 0x or suffixed with h. Add --dummy first: it builds the command but does not send it:
$ sudo sg_reassign --dummy --verbose \
--address=123456 /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
sudo appears here because opening a real block device usually needs elevated access, though the exact requirement is host-specific. Use the least privilege that works. With --verbose, check the diagnostic output and parameter block. This dummy run is your checkpoint for spelling, device selection, address format and the 4-byte versus 8-byte address choice.
For several addresses at once, comma-separate them:
$ sudo sg_reassign --dummy --verbose \
--address=123456,123457 /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
Unless told otherwise, the utility uses 4-byte logical block addresses when everything fits, and switches to 8-byte values once an address reaches 2^32. Set --eight=1 explicitly when your device and review need the long form, or --eight=0 when 4-byte addresses are appropriate. --longlist controls a CDB field the manual says there should normally be no reason to set; the utility caps you at 1000 addresses regardless.
4. Send one address at a time for the live operation
The local manual warns that if a later address in a multi-address request fails, earlier addresses may already have been reassigned. Repeat the whole list and you can consume spare locations twice over on those earlier entries. Unless you have a strong reason to batch them, run one address at a time and record each result.
Once the dummy output checks out, remove only --dummy for the live command. This is the point at which the device state actually changes:
$ sudo sg_reassign \
--address=123456 /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
$ printf 'exit status: %s\n' "$?"
exit status: 0
Exit status 0 means the utility completed successfully. It does not repair a filesystem, rewrite user data, or guarantee that the underlying media will remain healthy. Keep the original device in service only if your storage design and monitoring policy allow it.
There is no undo command. Reassigning the same logical block again is not a reversal and may consume another spare location. If the command fails with a hardware error, or a message equivalent to no defect spare location being available, stop. The documented next choices are reformatting the disk or replacing it, subject to your recovery plan.
5. Verify and monitor the result
Re-run the passive grown-list query and compare it with the count recorded before the operation:
$ sudo sg_reassign --grown /dev/disk/by-id/scsi-REPLACE_WITH_THE_DEVICE_ID
Do not invent a required count, and do not expect the output to identify your specific address. The useful checks are that the query completes, the device remains accessible, and your monitoring records the before and after values. For the contents of the grown list itself, the manual points to sginfo -G. Regular self-tests, using an appropriate tool such as sg_senddiag or smartmontools, are part of a wider storage-health process, not a substitute for backups.
Automatic reassignment can already be enabled by the device's Read Write Error Recovery mode page. The ARRE and AWRE fields affect automatic reassignment after recoverable read and write errors, while PER controls whether recovered errors are reported. Those settings are separate from this command. Inspect them with a suitable mode-page tool before changing any error-recovery policy, and avoid making unrelated mode-page changes during an incident.
Common traps
- Confusing a query with a repair.
--grownand--primaryonly read defect data. A live reassignment requires--addressand no--dummy. - Using the wrong address base. The option takes logical block addresses, not byte offsets. Confirm the value from the device error report or a trusted diagnostic.
- Assuming spare capacity is unlimited. Spare locations are vendor-specific and may be limited to a media zone.
- Batching a risky list. Earlier addresses can succeed before a later one fails. Prefer one address per invocation.
- Running as root by habit. Use
sudoonly for the device operation if permissions require it. Version checks and documentation do not need elevation.
Done means
- Device and address confirmed. The device path and logical block address were independently confirmed.
- Defect lists recorded. The grown and, where useful, primary defect-list counts were recorded first.
- Dummy run reviewed. A dummy, verbose invocation was checked before any live command.
- One address at a time. The live request used one address unless batching was explicitly justified.
- Result logged. The exit status and post-operation grown-list query were recorded.
- Backups still in place. Backups, self-tests and replacement planning remain, because reassignment is not a cure for failing media.