pub struct Checksummer {
pub seed: u32,
pub enabled: bool,
}Expand description
Per-mount checksum context: the seed and “is it enabled” flag.
Fields§
§seed: u32§enabled: boolImplementations§
Source§impl Checksummer
impl Checksummer
Sourcepub fn from_superblock(sb: &Superblock) -> Self
pub fn from_superblock(sb: &Superblock) -> Self
Derive the checksum context from a parsed superblock.
Per spec: if INCOMPAT_CSUM_SEED is set, use the explicit
s_checksum_seed field. Otherwise, the seed is crc32c(~0, UUID)
(format documentation, s_checksum_seed) — i.e. our
linux_crc32c(!0, UUID).
Sourcepub fn crc(&self, data: &[u8]) -> u32
pub fn crc(&self, data: &[u8]) -> u32
Linux-semantics CRC32C of a buffer using the mount-wide seed.
Sourcepub fn crc_with_prefix(&self, prefix: u32, data: &[u8]) -> u32
pub fn crc_with_prefix(&self, prefix: u32, data: &[u8]) -> u32
Linux-semantics CRC32C with a 32-bit context prefix folded in first.
Sourcepub fn verify_superblock(&self, sb_raw: &[u8]) -> bool
pub fn verify_superblock(&self, sb_raw: &[u8]) -> bool
Verify the superblock checksum. Stored at byte offset 0x3FC; CRC
covers the first 0x3FC bytes. Initial seed is ~0 (NOT the per-FS
seed — superblock checksum is special since the seed lives inside it).
Sourcepub fn verify_bgd(&self, group_no: u32, bgd_raw: &[u8], desc_size: u16) -> bool
pub fn verify_bgd(&self, group_no: u32, bgd_raw: &[u8], desc_size: u16) -> bool
Verify a block group descriptor’s checksum.
Per spec (ext4/group_descr.html), when RO_COMPAT_METADATA_CSUM is
set the GDT checksum is computed as:
crc32c(seed, group_no_le_u32 || bgd_with_csum_zeroed) & 0xFFFFdesc_size is the on-disk descriptor size (32 or 64).
bgd_raw must be at least desc_size bytes; the stored checksum at
offset 0x1E is treated as zero for the computation.
Sourcepub fn verify_dir_entry_tail(
&self,
ino: u32,
generation: u32,
block: &[u8],
) -> bool
pub fn verify_dir_entry_tail( &self, ino: u32, generation: u32, block: &[u8], ) -> bool
Verify a directory block’s trailing ext4_dir_entry_tail checksum.
Linear directory blocks with metadata_csum enabled end in a 12-byte
struct ext4_dir_entry_tail { u32 det_reserved_zero1; u16 det_rec_len; u8 det_reserved_zero2; u8 det_reserved_ft; u32 det_checksum; }.
The format documentation’s checksum table (“Directory Entries”): the
CRC covers block[0..block_size - 12] — i.e. everything BEFORE
the fake entry that holds it.
The tail’s own bytes (including det_checksum) are excluded:
crc32c(seed, ino_le) → crc32c(., gen_le) → crc32c(., block[..len-12])block is the whole directory block including the trailing tail.
Sourcepub fn patch_dir_entry_tail(
&self,
ino: u32,
generation: u32,
block: &mut [u8],
) -> bool
pub fn patch_dir_entry_tail( &self, ino: u32, generation: u32, block: &mut [u8], ) -> bool
Plant the ext4_dir_entry_tail and checksum a directory block.
The mirror of Self::verify_dir_entry_tail, and the sibling
that was missing: patch_extent_tail and patch_xattr_block
both existed, so the one recipe written most often was the one
with no helper. It was hand-rolled at sixteen sites across
fs.rs, fsck.rs, mkfs.rs and the tests, in two different
addressing idioms (bs - 12 with +4/+6/+7, and
block.len() with -8/-6/-5) that a reader has to prove
equivalent at each one.
The tail is a fake directory entry occupying the last 12
bytes: inode = 0 so no scan mistakes it for a real one,
rec_len = 12 so a walk steps over it, name_len = 0, and
file_type = 0xDE as the marker has_csum_tail looks for. The
CRC then covers block[..len - 12] — the whole block except
the tail entry, which is what separates this from
Self::patch_extent_tail, where only the trailing 4 bytes are
excluded.
Planting is idempotent: a block that already carries the tail gets the same twelve bytes back, so callers that only need the checksum recomputed can use this too rather than keeping a second recipe for that case.
Every constant here has to agree with e2fsprogs, and a disagreement produces no error until the volume is mounted somewhere else — which is the argument for there being one copy of them.
No-op when checksums are disabled or the block is under 12 bytes; returns true when it patched.
Sourcepub fn verify_dx_tail(
&self,
ino: u32,
generation: u32,
block: &[u8],
count_offset: usize,
) -> Option<bool>
pub fn verify_dx_tail( &self, ino: u32, generation: u32, block: &[u8], count_offset: usize, ) -> Option<bool>
Whether an htree block’s dx_tail checksum is the one its contents
give: Some(true) or Some(false), or None when checksums are off
or the count/limit pair leaves no room for a tail to check.
The same computation as Checksummer::patch_dx_tail, compared
rather than written.
Sourcepub fn patch_dx_tail(
&self,
ino: u32,
generation: u32,
block: &mut [u8],
count_offset: usize,
) -> bool
pub fn patch_dx_tail( &self, ino: u32, generation: u32, block: &mut [u8], count_offset: usize, ) -> bool
Recompute the checksum in an htree block’s dx_tail.
The “HTREE Nodes” row of the format documentation’s checksum table:
crc32c over the inode number and
generation, the block up to the last used dx_entry, and the tail’s
reserved word, with the checksum field itself counted as zero. The
tail sits right after limit entries. count_offset is where the
count/limit pair starts: 32 in a dx_root, 8 in an interior node.
Returns false (and writes nothing) when checksums are off or the
count/limit pair does not leave room for a tail in this block.
Sourcepub fn verify_extent_tail(
&self,
ino: u32,
generation: u32,
block: &[u8],
) -> bool
pub fn verify_extent_tail( &self, ino: u32, generation: u32, block: &[u8], ) -> bool
Verify an extent-block tail checksum.
Extent index/leaf blocks (those read off-inode when the tree has
internal nodes) end in a 4-byte struct ext4_extent_tail { u32 et_checksum; }. Per the “Extents” row of the format
documentation’s checksum table the CRC covers block[0..len-4]
— only the trailing et_checksum field is excluded:
crc32c(seed, ino_le) → crc32c(., gen_le) → crc32c(., block[..len-4])Different from verify_dir_entry_tail, which excludes the full
12-byte tail entry.
Sourcepub fn verify_inode(&self, ino: u32, generation: u32, inode_raw: &[u8]) -> bool
pub fn verify_inode(&self, ino: u32, generation: u32, inode_raw: &[u8]) -> bool
Verify a parsed inode’s checksum. Chained: seed → ino_le → gen_le → inode_bytes (with checksum slots zeroed).
Sourcepub fn patch_extent_tail(
&self,
ino: u32,
generation: u32,
block: &mut [u8],
) -> bool
pub fn patch_extent_tail( &self, ino: u32, generation: u32, block: &mut [u8], ) -> bool
Write the ext4_extent_tail.et_checksum u32 at the end of a freshly-
built extent index/leaf block. Mirrors verify_extent_tail: the CRC
covers block[..len-4], chained seed → ino → generation → body.
No-op when checksums are disabled; returns true when it patched.
Sourcepub fn verify_xattr_block(&self, block_nr: u64, block: &[u8]) -> bool
pub fn verify_xattr_block(&self, block_nr: u64, block: &[u8]) -> bool
Verify an external xattr block’s checksum.
The format documentation’s checksum table gives the block with its checksum field zeroed; the block number goes in ahead of it as well, and blocks the kernel and e2fsprogs write verify this way. The recipe is:
crc32c(seed, block_nr_le_u64)
→ crc32c(., block[0x00..0x10]) // magic, refcount, blocks, hash
→ crc32c(., [0u32]) // h_checksum slot zeroed (4 bytes)
→ crc32c(., block[0x14..end]) // rest of blockThe stored u32 lives at offset 0x10 of the block.
Sourcepub fn patch_xattr_block(&self, block_nr: u64, block: &mut [u8]) -> bool
pub fn patch_xattr_block(&self, block_nr: u64, block: &mut [u8]) -> bool
Patch the h_checksum field of an external xattr block in place.
Mirrors [verify_xattr_block]. No-op when checksums are disabled.
Returns true when the block was patched.
Sourcepub fn compute_inode_checksum(
&self,
ino: u32,
generation: u32,
inode_raw: &[u8],
) -> Option<(u16, u16)>
pub fn compute_inode_checksum( &self, ino: u32, generation: u32, inode_raw: &[u8], ) -> Option<(u16, u16)>
Compute the inode checksum as two u16 halves (lo=checksum_lo at 0x7C,
hi=checksum_hi at 0x82). Returns None when checksums are disabled
or the buffer is too short to patch. Callers use this after mutating
an inode image to restore the checksum before writing back.