I purchased two refurb'd Samsung PM1643a SSDs (OEM model: SLM5B-M3R8SS) and installed them in a Dell R740 Proxmox server with a PERC H330 controller. The drives were previously used in an enterprise storage array (likely Hitachi/HDS or EMC) and formatted with 520-byte sectors instead of the standard 512-byte sectors. This made them pretty unusable without flashing my H330 to IT-mode, which would require unacceptable downtime.
| Slot | Serial | Result |
|---|---|---|
| 4 | B4YEK05H | ✅ Fixed - /dev/sdf |
| 5 | B4YEK0GR | ✅ Fixed - /dev/sdg |
- Drive shows as "UGUnsp" (Unconfigured Good Unsupported) in perccli
- Logical Sector Size: 0 KB reported by controller
- Size: 0 KB - controller can't read capacity
- Drive is NOT exposed to Linux as
/dev/sd*or/dev/sg* - Samsung DC Toolkit cannot see the drive
sg_formatcannot access the drive- All standard erase/format commands via perccli fail with "Operation not allowed"
smartctl -d megaraid,4 -i /dev/sda
Logical block size: 520 bytes
Physical block size: 4160 bytes
The PERC H330 (and most RAID controllers) only support 512-byte or 4096-byte sectors. The 520-byte format includes 8 extra bytes per sector for T10-DIF data integrity protection, used by enterprise storage arrays.
I discovered that while the PERC H330 won't expose the drive to Linux, smartctl can communicate with it via the MegaRAID passthrough IOCTL. So with the help of Claude Code I reverse-engineered the IOCTL interface from smartctl's source code and created custom tools to send SCSI commands directly to the drive.
The MegaRAID driver (megaraid_sas) provides a passthrough interface at /dev/megaraid_sas_ioctl_node that allows sending SCSI commands to physical drives, even those marked as "unsupported."
Tests SCSI passthrough by sending an INQUIRY command to verify communication with the target drive.
Usage:
gcc -o mega_inquiry mega_inquiry.c
./mega_inquiry /dev/sda <target_id>Sends a FORMAT UNIT SCSI command to reformat the drive to 512-byte sectors.
Usage:
gcc -o mega_format512 mega_format512.c
./mega_format512 /dev/sda <target_id>Note: This worked on Drive 1 (slot 4) - it reported "status 45" failure but actually succeeded!
That drive's mode page evidently already read 512, since FORMAT UNIT on its own
cannot change the sector size (see the next note); don't count on that.
See "The IMMED bit" below for why status 45 (MFI_STAT_SCSI_IO_FAILED) shows up here.
Note: FORMAT UNIT has no block-size field - the sector size comes from a
preceding MODE SELECT. This tool only sends FORMAT UNIT, so it relies on the
drive's current mode page. If it leaves the drive at 520, use mega_modesel or
mega_format_immed, which set the block size first.
Until this was fixed, mega_format512 sent a 12-byte MODE SELECT block
descriptor as its FORMAT UNIT parameter list. The drive decoded bytes 2-3 as
DEFECT LIST LENGTH = 8 and the remaining eight bytes as two short-block defect
descriptors, so every run added LBA 0 and LBA 512 to the drive's grown defect
list. LBA 0 is the partition table.
The current tools no longer add them - but they do not remove them either. All
three formatters send CMPLST=0, which means an existing grown list is kept
across a format, so the entries persist indefinitely. Affected drives still work
(the LBAs are transparently redirected to spare sectors); this is a latent
oddity worth clearing, not an outage.
To check and remediate a drive formatted by an older build:
⚠️ The device argument below is NOT the one themega_*tools take. Everywhere else in this README,/dev/sdais a passthrough handle - any healthy drive on the same controller, used only to look up the host number, never written to. Thesg_*commands here address the target drive directly, so passing/dev/sdaout of habit points a destructive root command at whateversdahappens to be, quite possibly your boot disk. Confirm the node withlsscsifirst and pass that.These commands also need the drive visible to Linux as an ordinary SCSI device.
sg3-utilshas no MegaRAID passthrough, so they cannot reach a drive the controller is still hiding - that is the whole reason the tools in this repo exist. Use them only after the reformat has succeeded and the drive shows up as JBOD.
# Identify the real device node for the drive - do NOT guess
lsscsi
# List the grown defect list - look for LBA 0 and LBA 512
sg_defects -G /dev/sdX
# Clear it during a format by declaring the supplied list complete (CMPLST=1).
# DESTROYS ALL DATA on /dev/sdX, and takes hours on a multi-TB HDD.
sg_format --format --cmplst=1 --size=512 /dev/sdXsg_format defaults to --cmplst=1; these tools deliberately do not, so that a
routine reformat never discards genuine media defects the drive has recorded.
Because these tools also format with DCRT=0, the drive re-certifies the medium
as it goes, so hard defects are re-discovered and re-added - clearing the grown
list is less lossy than it sounds, but it is still not the default here.
Uses MODE SELECT to set block size to 512, then FORMAT UNIT to apply. This was needed for Drive 2 (slot 5) where the direct FORMAT UNIT approach didn't work.
Usage:
gcc -o mega_modesel mega_modesel.c
./mega_modesel /dev/sda <target_id>Validates that the MegaRAID IOCTL structures match the expected sizes (404 bytes for megasas_iocpacket).
Same idea as mega_modesel.c (MODE SELECT to 512, then FORMAT UNIT) but the
FORMAT UNIT is sent with the IMMED bit set so it returns immediately and the
drive formats in the background. This makes the reformat reliable on slow,
multi-TB spinning drives, not just fast SSDs (see "The IMMED bit" below).
Usage:
gcc -o mega_format_immed mega_format_immed.c
./mega_format_immed /dev/sda <target_id>
# then poll progress every 60s until it finishes:
./mega_progress /dev/sda <target_id> 60Sends REQUEST SENSE and reports background format progress. While a format runs
the drive answers with sense key 0x2 / ASC 0x04 / ASCQ 0x04
("LOGICAL UNIT NOT READY, FORMAT IN PROGRESS") plus a 0-65535 progress value.
REQUEST SENSE is sent with DESC=0, so a conformant drive answers in
fixed format (0x70/0x71); the descriptor-format (0x72/0x73) decoder is
defensive hardening rather than a path that normally runs. Progress bytes are
trusted only when the drive supplies one - SKSV for the fixed layout and for
descriptor type 0x02, or the presence of descriptor type 0x0A, which carries
progress with no SKSV bit - and only when the sense key is one where those
bytes mean progress - under ILLEGAL REQUEST the same field is a pointer to the
offending CDB byte, and under MEDIUM ERROR it is a retry count.
Once no format is in progress it issues READ CAPACITY(10) and reports
the drive's actual block size - completion is not inferred from a sense key
of 0x0, which equally means "nothing has happened yet".
Usage:
gcc -o mega_progress mega_progress.c
# report once and exit
./mega_progress /dev/sda <target_id>
# FORMAT IN PROGRESS: 42.0% (27524/65536)
# or poll every 60s until the format finishes
./mega_progress /dev/sda <target_id> 60
# ...
# Drive ready: block size 512 bytes, 3907029168 blocks (2.00 TB)Exit status: 0 = ready at 512 bytes, 2 = ready but not at 512 bytes,
3 = not confirmed complete (still formatting, not ready, or a UNIT ATTENTION
got in the way), 1 = error.
3 is deliberately not success: the decision it gates is whether to power
cycle the drive, and a drive must not lose power mid-format. Note that 3 is
only ever returned by the one-shot form - in polling mode the tool keeps
polling instead of returning "still busy". So the gate is:
# one-shot: 0 only if the drive is ready AND at 512 bytes
./mega_progress /dev/sda 4 && power_cycleBoth 2 (wrong block size) and 3 (not confirmed complete) block the power
cycle, which is the safe direction to be wrong in.
By default FORMAT UNIT does not return until the entire format finishes.
Sent through the MegaRAID passthrough that causes a subtle, drive-dependent bug:
- On a fast SSD, the format finishes in seconds/minutes - sometimes before the
RAID controller's command timeout - so the tool appears to work (this is the
origin of the "status 45 failure but it actually worked" note above; status
45 =
MFI_STAT_SCSI_IO_FAILED). - On a slow multi-TB 7200rpm HDD, the format takes hours. The controller's
command timeout fires long before completion and aborts the command with
SCSI_IO_FAILED. The drive is left half-formatted and invalid: a SMART self-test returns "Input/output error", and the controller reports0 KB/UBad. (Note:smartctlmay still print512 bytes / <full capacity>- that is the intended geometry from the mode page, not proof the medium is good.)
Setting the IMMED bit in the FORMAT UNIT parameter-list header fixes this: the
drive validates the request, returns immediately, and formats in the background.
You then poll with mega_progress. mega_format_immed.c sets IMMED; the other
formatters do not. If a no-IMMED attempt left a drive half-formatted, just run
mega_format_immed and let it complete - the medium recovers once a format
finishes.
# List all drives - look for UGUnsp state and 0 KB size
/opt/MegaRAID/perccli/perccli64 /c0 /eall /sall show
# Confirm 520-byte sectors via smartctl passthrough
smartctl -d megaraid,<target_id> -i /dev/sdaThis choice matters - picking wrong can leave the drive unusable.
| Drive | Use | Why |
|---|---|---|
| SSD | mega_format512, then mega_modesel if that fails |
Format completes inside the controller's command timeout |
| Spinning HDD, or anything over ~1 TB | mega_format_immed + mega_progress |
A blocking FORMAT UNIT takes hours, hits the controller timeout, and leaves the medium half-formatted and invalid |
Do not run mega_format512 or mega_modesel against a slow multi-TB HDD - see
"The IMMED bit" above for what goes wrong and how to recover.
HDD path:
gcc -o mega_format_immed mega_format_immed.c
gcc -o mega_progress mega_progress.c
./mega_format_immed /dev/sda <target_id>
# poll every 60s until it finishes (hours on a multi-TB drive)
./mega_progress /dev/sda <target_id> 60SSD path:
# Compile and run
gcc -o mega_format512 mega_format512.c
./mega_format512 /dev/sda <target_id>
# Check if it worked (even if it reported failure!)
smartctl -d megaraid,<target_id> -i /dev/sda | grep "block size"This continues the SSD path from Step 2. Do not run it on a slow or multi-TB
HDD - mega_modesel sends a blocking FORMAT UNIT and has the same
half-formatting failure mode as mega_format512. On the HDD path,
mega_format_immed already did the MODE SELECT.
# Compile and run
gcc -o mega_modesel mega_modesel.c
./mega_modesel /dev/sda <target_id>
# Check result
smartctl -d megaraid,<target_id> -i /dev/sda | grep "block size"The PERC controller caches the "unsupported" state. Even after successful format, perccli may still show UGUnsp. You MUST do one of:
Option A: Hot-reseat the drive (preferred)
- Physically unplug and replug the drive
- This forces the controller to re-discover it fresh
Option B: Reboot the server
- Only if hot-swap isn't possible
Option C: Full COLD power cycle (chassis with no hot-swap backplane)
- On some servers the drives are cabled directly (no backplane / SES), so you
can't hot-reseat, and a warm reboot is not enough: after the format the drive
drops into a low-power state and a warm reboot leaves it powered, so the
controller just re-reads its stale
UGUnsp/0 KBidentity. Power the machine fully off, wait ~30s so the drive spins down and loses power, then power on. The controller then discovers it cleanly as a 512-byte JBOD.
# Check perccli - should show JBOD with correct size
/opt/MegaRAID/perccli/perccli64 /c0/e32/s<slot> show
# Check Linux sees it
lsscsi -g | grep -i samsu
lsblk
# Full verification
fdisk -l /dev/sdX
smartctl -a /dev/sdX- Ran
mega_format512- reported "status 45" failure - Checked smartctl - showed 512 bytes! (command actually worked)
- SCSI rescan picked it up as /dev/sdf
- No hot-reseat needed
- Ran
mega_format512- reported "status 45" failure - Checked smartctl - still 520 bytes (didn't work)
- Ran
mega_modesel(MODE SELECT + FORMAT) - reported success - Checked smartctl - showed 512 bytes!
- Controller still showed UGUnsp (stale cache)
- Hot-reseated the drive (unplug/replug)
- Controller recognized it as JBOD, appeared as /dev/sdg
| Property | Before | After |
|---|---|---|
| State | UGUnsp | JBOD |
| Size | 0 KB | 3.49 TiB |
| Logical Sector | 520 bytes | 512 bytes |
| Physical Sector | 4160 bytes | 4096 bytes |
| Linux Device | (none) | /dev/sdf, /dev/sdg |
| SMART Health | N/A | OK |
struct megasas_iocpacket {
u16 host_no; // SCSI host number (from SCSI_IOCTL_GET_BUS_NUMBER)
u16 __pad1;
u32 sgl_off; // Offset to scatter-gather list in frame
u32 sge_count; // Number of SG elements
u32 sense_off;
u32 sense_len;
union {
u8 raw[128];
struct megasas_pthru_frame pthru; // Passthrough frame
} frame;
struct iovec sgl[16]; // Scatter-gather list (userspace pointers)
};- INQUIRY (0x12) - Identify drive
- MODE SENSE (0x1A) - Read current block descriptor
- MODE SELECT (0x15) - Set new block size
- FORMAT UNIT (0x04) - Apply new format
- READ CAPACITY (0x25) - Verify block size
# Check drive status in perccli
/opt/MegaRAID/perccli/perccli64 /c0/e32/s<slot> show all
# Read drive info via smartctl passthrough
smartctl -d megaraid,<target_id> -a /dev/sda
# List all drives
/opt/MegaRAID/perccli/perccli64 /c0 /eall /sall show
lsscsi -gOn the Proxmox/Linux host:
apt-get install build-essential smartmontools sg3-utils lsscsi| File | Description |
|---|---|
mega_format512.c |
FORMAT UNIT tool - try this first on SSDs (not on slow HDDs) |
mega_modesel.c |
MODE SELECT + FORMAT tool - use if format512 fails on SSDs |
mega_format_immed.c |
MODE SELECT + FORMAT UNIT with IMMED (background format; reliable on slow HDDs) |
mega_progress.c |
Poll background FORMAT UNIT progress via REQUEST SENSE |
mega_inquiry.c |
INQUIRY test tool to verify passthrough works |
check_size.c |
Structure size validation tool |
README.md |
This documentation |
- Always verify with
smartctl -d megaraid,X -i /dev/sda | grep block, or with./mega_progress /dev/sda <target_id>which reports the drive's real block size - Status 45 (MFI_STAT_SCSI_IO_FAILED) doesn't always mean failure
- On a slow HDD it usually means the controller timed out a blocking
FORMAT UNITand the medium is now half-formatted - usemega_format_immedinstead. See "The IMMED bit" above.
- The controller has stale cache
- Hot-reseat the drive (physically unplug and replug)
- Or reboot the server
- Try again with
mega_format_immed, which is the reliable path. Do not repeatedly re-run the blocking formatters: on a slow HDD each attempt times out and re-damages the medium, and older builds also added a defect-list entry every run (see above) - Some drives may need specific firmware
- May need to try in a different system with direct HBA access (LSI 9211-8i in IT mode)
- Usually means controller cache is stale
- Hot-reseat should fix this
- smartmontools source - megaraid.h
- smartmontools source - os_linux.cpp
- Level1Techs - Reformat 520 to 512 bytes
- setblocksize tool
Created: January 2026 Successfully used on Samsung PM1643a (OEM: SLM5B-M3R8SS) on Dell R740 with PERC H330 Two drives reformatted from 520-byte to 512-byte sectors via MegaRAID passthrough IOCTL
Also validated on Dell PowerEdge T130 with PERC H730 (HBA-mode) reformatting
2 TB HGST HMRP2000 7200rpm SAS HDDs. On these slow HDDs the non-IMMED FORMAT UNIT
timed out and left the medium half-formatted; mega_format_immed + mega_progress
(this PR) made it reliable, and a full cold power cycle was required to clear the
controller's stale cache (contributed by @mwventures).