Master the fundamental concepts of file systems through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksext2 partitions disk into block groups, each with superblock copy, block bitmap, inode bitmap, inode table, and data blocks. It teaches modern ext4 without journaling complexity.
Per group:
0xEF53, counts, feature flagsFor example, inode 12 in group 0 might live at byte offset inode_table_start + 11 * inode_size.
The block-group layout you're parsing here is the direct ancestor of ext3 and ext4 , the default filesystem on most Linux servers , which still uses the same superblock magic number (0xEF53) and inode-table structure. Getting the block-size-to-log_block_size formula wrong (1024 << log_block_size) means every subsequent offset calculation reads garbage instead of real metadata.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will read an ext2 image and print superblock fields plus inode 2 (root) mode and size. This exercise requires decoding direct block pointers for a small file.
Decode an ext2 superblock and compute the filesystem's on-disk layout. ext2 splits the disk into block groups. Each group has a block bitmap, an inode bitmap and an inode table, and some groups start with a backup copy of the superblock and the group descriptor table. From the superblock alone you can work out where every structure lives, which inode-table block holds any inode, and what any block number is used for. ext3 and ext4 still use this layout.
The first 1024 bytes of the superblock as a sparse hex dump (OFFSET: b0 … b15; missing lines are zero), ending with end. Then commands: info, groups, inode N, block N.
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | inodes count |
| 4 | 4 | blocks count |
| 8 | 4 | reserved blocks |
| 12 | 4 | free blocks |
| 16 | 4 | free inodes |
| 20 | 4 | first data block |
| 24 | 4 | log block size (block size = 1024 << value) |
| 32 | 4 | blocks per group |
| 40 | 4 | inodes per group |
| 56 | 2 | magic (must be 0xEF53) |
| 76 | 4 | revision level |
| 88 | 2 | inode size (only if revision ≥ 1; otherwise 128) |
| 120 | 16 | volume name (NUL-padded) |
mke2fs builds it, without reserved GDT blocks)groups = ⌈(blocks − first data block) / blocks per group⌉, gdt blocks = ⌈groups × 32 / block size⌉, and inode table blocks = ⌈inodes per group × inode size / block size⌉.g spans blocks first + g × bpg up to first + (g+1) × bpg − 1; the last group may be cut short by the block count.N (numbered from 1) is in group (N−1) / ipg at index (N−1) mod ipg. Its byte offset within that group's inode table is index × inode size.cLoading…
(1 block / N blocks for the GDT.)
groups: group G: blocks S-E[, superblock S, gdt A-B], block bitmap X, inode bitmap Y, inode table P-Q, data R-Einode N: group G, index I, block B, offset O, where B is the absolute block and O the byte offset within it.block N: group G, offset K, KIND, where KIND is one of superblock, group descriptors, block bitmap, inode bitmap, inode table or data. Blocks before the first data block are block N: boot block (before the first group).inode N: out of range (1..MAX) / block N: out of range (0..MAX).bad magic 0xXXXX: not an ext2 filesystem and ignores the commands.Input:
cLoading…
Output:
cLoading…
group_layout(g) function computes every region of a group; groups, inode and block all use it.Hidden tests cover a filesystem with enough groups for the sparse_super rule to skip most of them, a two-block group descriptor table, an inode in a late group, blocks in every kind of region, an out-of-range block, and a bad magic number.