work / systems / vsfsck
VSFSck
A file-system consistency checker in C that validates and repairs superblocks, bitmaps, inodes, and data blocks in a 64-block virtual file system.
- image
- 64 blocks
- 4096 B each, 256 KiB total
- inode size
- 256 B
- blocks 3-7 inode table
- checks
- 5 validators
- superblock to bad blocks
- magic
- 0xd34d
- superblock signature
system architecture / interactive
What an fsck actually does
When a file system is interrupted mid-write, its on-disk metadata can disagree with itself: a
bitmap says a block is free while an inode still points at it, or two inodes claim the same
block. Tools like fsck walk the raw image and reconcile these stories. VSFSck implements
that logic for the Very Simple File System (VSFS), a teaching file system with a fixed
layout, operating directly on a binary vsfs.img.
The on-disk layout
The image is 64 blocks of 4096 bytes: block 0 is the superblock, block 1 the inode bitmap, block 2 the data bitmap, blocks 3-7 the inode table (256-byte inodes), and blocks 8-63 the data region. Everything the checker knows, it learns by seeking and reading structs out of this raw layout, there is no file API to lean on.
The five validators
- Superblock validation: magic number
0xd34d, block size 4096, total blocks 64, valid metadata pointers, and sane inode size and count. - Data bitmap consistency: every block marked used must be referenced by a valid inode, and every block an inode references must be marked used, checked in both directions.
- Inode bitmap consistency: every set bit must correspond to an inode with
link_count > 0anddeletion_time == 0. - Duplicate block detection: no data block may be claimed by more than one inode.
- Bad block detection: every reference must land inside the valid data region (8-63).
What it taught
The interesting engineering is in the cross-checks: each rule requires holding two views
of the file system (what the bitmaps claim versus what the inode table actually references)
and reconciling them bit by bit. Off-by-one errors in block indexing corrupt everything
downstream, so the code treats boundaries (the 8-63 data region, the five inode-table blocks)
as named constants and validates against them everywhere. Debugging happened at the hex level
with ghex, which is the honest way to learn what "the file system is just bytes" means.
stack