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 the kernel’s
__crc32c_le(~0, UUID, 16) — 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; }.
Per Linux fs/ext4/dir.c::ext4_dirent_csum_set the CRC covers
block[0..block_size - 12] — i.e. everything BEFORE the tail.
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_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 Linux
fs/ext4/extents.c::ext4_extent_block_csum_set 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.
Per Linux fs/ext4/xattr.c::ext4_xattr_block_csum, 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.
Trait Implementations§
Source§impl Clone for Checksummer
impl Clone for Checksummer
Source§fn clone(&self) -> Checksummer
fn clone(&self) -> Checksummer
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more