Β§45.1–45.3Disk Failure Modes and Detecting Corruption with Checksums

Part III OSTEP pp. 587–592 Β· ~15 min read

  • data integrity
  • fail-stop
  • fail-partial
  • latent sector error
  • block corruption
  • silent fault
  • error correcting code
  • checksum
  • fletcher checksum
  • cyclic redundancy check
  • checksum collision

Data integrity (or data protection) asks a question RAID’s whole-disk reliability didn’t: when a storage device hands a block back, is it really the block you stored? Modern disks mostly work β€” but occasionally return a bad block, sometimes without even knowing it.

The Crux: How To Ensure Data Integrity

How should systems ensure that data written to storage is protected? What techniques are required, and how can they be made efficient β€” in both space and time?

45.1 Disk Failure Modes

Early RAID assumed the fail-stop model: a disk is either entirely working or entirely, detectably dead. Real disks are messier. The fail-partial model (from the IRON File Systems study) says a disk can seem healthy yet have individual blocks fail:

fail-stop (early RAID)the whole disk is dead β€” and easy to detectfail-partial (real disks)βœ—?βœ— = LSE (unreadable, errors) ? = corruption (silent, wrong)

Two single-block faults matter, and they differ in one crucial way β€” whether the disk knows something is wrong:

  • A latent sector error (LSE): a sector is physically damaged (a head crash, a cosmic-ray bit flip). The drive’s in-disk error correcting codes (ECC) catch the bad bits and, if they can’t repair them, return an error. Loud and detected.
  • Block corruption : the block holds the wrong contents (buggy firmware misdirected a write; a faulty bus garbled the bytes) but ECC still says it’s fine. The disk returns bad data with no warning β€” a silent fault .
The two single-block faults of the fail-partial model β€” one loud, one silent.
latent sector error (LSE)block corruption
causesector physically damaged β€” head crash, cosmic-ray bit flipbuggy firmware writes to the wrong place, or bits garble over a faulty bus
does the disk notice?yes β€” in-disk ECC flags the bad bitsno β€” ECC still says the block is good
silent?non-silent β€” returns an explicit errorSILENT β€” returns wrong data as if correct
detected bythe drive itself, on the reada checksum kept by the file system / controller
recovered byredundancy β€” mirror copy or parity reconstructionredundancy too β€” but only once detection tells you it is bad
Dotted-underlined cells have explanations β€” click one.

Just how often? Over ~1.5 million drives across three years, LSEs and corruption were rare but far from negligible:

Figure 45.1: fraction of drives that showed at least one fault over ~3 years (Bairavasundaram et al., ~1.5 million drives). Costlier drives fail ~10Γ— less β€” but not never.
β‰₯1 latent sector errorβ‰₯1 block corruption
cheap drives (SATA)9.40%0.50%
costly drives (SCSI / FC)1.40%0.05%
Dotted-underlined cells have explanations β€” click one.

The studies found more texture worth knowing: faults cluster in space and time (a disk with one LSE tends to get more, nearby); the annual LSE rate rises in a drive’s second year and grows with disk size; corruption rates vary wildly between models of the same class; and corruption is only weakly correlated with LSEs. The takeaway is blunt: a reliable storage system must include machinery to detect and recover from both.

45.2 Handling Latent Sector Errors

LSEs are the easy case, precisely because they are detected. When a read returns an error, the system just rebuilds the block from whatever redundancy it has β€” the mirror copy in a mirrored RAID, or the parity group in RAID-4/5.

There is one nasty corner, though. When a whole disk dies and the RAID rebuilds it by reading every other disk in the parity group, an LSE on one of those disks means two blocks are missing at once β€” more than a single parity can recover:

RAID-4/5 survives one failure β€” but a latent sector error DURING reconstruction is a second fault the single parity cannot cover. RAID-DP adds a second parity disk (a second equation) to recover both.
Disk 0D0Disk 1D1Disk 2D2Disk 3D3Disk 4Pone parity = one recoverable failure per stripe

1A healthy parity stripe

Four data blocks plus one parity block (P = D0 βŠ• D1 βŠ• D2 βŠ• D3). Any single lost block can be recomputed from the others plus parity.

step 1 / 4

NetApp’s RAID-DP answers this with a second parity disk β€” a second independent equation β€” so a full-disk failure plus a stray LSE can still be reconstructed. The cost is an extra parity block per stripe (softened by WAFL’s log-structured writes). As always, redundancy is the key to both detection and recovery.

45.3 Detecting Corruption: The Checksum

Silent corruption is the hard case: before you can recover a bad block, you have to know it’s bad. The workhorse for detection is the checksum β€” a small summary (say 4–8 bytes) computed over a data block (say 4 KB). Store it with the data; on every read, recompute it and compare. A mismatch means the data changed since it was written.

Common checksum functions

Different functions trade strength against speed. The simplest is XOR: fold every chunk of the block together with exclusive-or into one word. Here it is on a 16-byte block:

A 4-byte XOR checksum over a 16-byte block. Lay the bytes in 4 rows of 4 bytes, then XOR the rows together column by column (bit position by bit position).
16 data bytes (hex) β€” 4 bytes per rowrow 136 5e c4 cdrow 2ba 14 8a 92row 3ec ef 2c 3arow 440 be f6 66

1The 16 bytes to protect

Our (tiny, for illustration) data block is 16 bytes. We want a 4-byte checksum summarizing it.

step 1 / 4

Tip: There’s No Free Lunch (TNSTAAFL)

The more protection a checksum gives, the more it usually costs to compute. When something looks free β€” a stronger check at no price β€” look again; you’re probably paying somewhere.

Stronger options climb the cost curve. Addition (2’s-complement, ignoring overflow) is fast but fooled by shifted data. The Fletcher checksum keeps two running bytes:

s1=(s1+di)β€Šmodβ€Š255s2=(s2+s1)β€Šmodβ€Š255\begin{aligned} s_1 &= (s_1 + d_i) \bmod 255 \\ s_2 &= (s_2 + s_1) \bmod 255 \end{aligned}

computed over every byte did_i β€” catching all single- and double-bit errors and many burst errors, almost as strongly as a CRC. The cyclic redundancy check (CRC) treats the block as one giant number and takes its remainder modulo an agreed value k; the binary modulo is cheap, which is why CRCs are everywhere (networking included).

Common checksum functions trade strength against speed β€” there is no free lunch.
how it worksstrengthspeed
XORXOR every chunk of the block into one wordweak β€” two flips in the same bit position cancelvery fast
addition2's-complement add each chunk, ignoring overflowweak β€” fooled if the data is merely shiftedvery fast
Fletchertwo running bytes s1, s2 (each mod 255)strong β€” all single-/double-bit and many burst errorsmoderate
CRCtreat the block as a big number; take remainder mod kstrongfast β€” the binary modulo is cheap to implement
Dotted-underlined cells have explanations β€” click one.

Whatever the function, no checksum is perfect: two different blocks can produce the same summary β€” a collision . That’s unavoidable when you squeeze 4 KB into 8 bytes; a good function just makes collisions rare while staying cheap.

Checksum layout: where do the checksums go?

Computing a checksum is only half the story β€” you also have to store it. Start with a plain run of data blocks and no protection:

no checksums β€” just data blocksD0D1D2D3D4D5D6

The natural fix is one checksum right before each block. But checksums are tiny (β‰ˆ8 bytes) and disks write in 512-byte sectors, so this needs special 520-byte sectors (8 extra bytes each) from the drive maker:

one checksum before each block (needs 520-byte sectors)C[D0]D0C[D1]D1C[D2]D2C[D3]D3C[D4]D4

On ordinary disks, the file system instead packs n checksums into one sector, followed by the n data blocks they cover:

n checksums packed in a sector, then n data blocksC[D0]C[D1]C[D2]C[D3]C[D4]D0D1D2D3D4

This works everywhere, but separating a block from its checksum costs I/O: to overwrite block D1 you must read its checksum sector, update C(D1), then write back both the checksum sector and the data β€” one read and two writes, where the per-sector layout needed just one write. Another instance of TNSTAAFL.

Check yourself: failure modes and checksums

1.How does the fail-partial model differ from the fail-stop model early RAID assumed?

2.Why is a latent sector error (LSE) much easier to handle than block corruption?

3.Why does an LSE encountered DURING a full-disk reconstruction break a single-parity RAID-4/5, and how does RAID-DP fix it?

4.What is a checksum, and why can two different blocks share one (a collision)?

5.What is the known weakness of a simple XOR-based checksum shown by the worked example?

6.Storing checksums packed together (n checksums in a sector, then n data blocks) works on any disk. What's the cost versus one checksum per (520-byte) sector?

6 questions