Exercises — ext4 structure — superblock, block groups, inodes
This page is a self-test ladder. Cover the solution, try the problem, then reveal. Every symbol used here was built in the parent topic under Operating Systems. If you get stuck on why a formula exists, re-read that note first — here we only apply it.
Two constants recur, so pin them down once:

Level 1 — Recognition
(Can you name the piece and pull the right fact?)
L1.1
Q: At what byte offset does the primary superblock live, and why not offset 0?
Recall Solution
Answer: byte offset 1024. The first 1024 bytes of the whole device are reserved for a boot sector (legacy space where boot code could sit). The filesystem is not allowed to scribble there, so its "ID card" — the superblock — starts immediately after, at byte offset 1024. Offset 0 is off-limits, not filesystem territory.
L1.2
Q: A block group with contains, in order, four/five regions. List them from the start of the group.
Recall Solution
In order:
- (optional) Superblock backup + Group Descriptor Table backup — only in some groups.
- Block bitmap (1 block) — used/free map of this group's blocks.
- Inode bitmap (1 block) — used/free map of this group's inodes.
- Inode table — the array of inode records.
- Data blocks — actual file contents.
Mnemonic order: bits before the things they count — you map free space (bitmaps) before you place records (inode table) and payload (data).
L1.3
Q: Which inode number is the root directory /, and what is the range of reserved inodes?
Recall Solution
Root is inode 2. Inodes 1–10 are reserved (inode 1 = bad-blocks list, inode 2 = root, inode 11 = lost+found by convention). Hardcoding root = 2 gives path resolution a fixed place to begin.
Level 2 — Application
(Plug numbers into the geometry formulas.)
L2.1
Q: With bytes, how many blocks per group, and how many MiB per group?
Recall Solution
Blocks per group = bits in one bitmap block = . Each block is 4096 bytes, so: (.)
L2.2
Q: A disk is formatted with bytes (1 KiB). How many blocks per group, and how many KiB per group?
Recall Solution
Blocks per group = blocks. Size = bytes KiB MiB per group. Notice: smaller block → smaller group. The bitmap always fits exactly one block, so shrinking shrinks both the bit-count and the block-size, and group size scales as bytes.
L2.3
Q: For , a 20 GiB disk. How many block groups (ignoring metadata overhead)?
Recall Solution
Group size = 128 MiB. Total = MiB.
Level 3 — Analysis
(Now the 1-based / 0-based reasoning bites.)
L3.1
Q: Inodes-per-group = 8192. Which block group holds inode number 50000, and what is its index inside that group's inode table?
Recall Solution
Inode numbers are 1-based, array indices are 0-based, so subtract 1 first. Index within that group: Group 6, index 847.
L3.2
Q: Same inodes/group. Show the danger: compute the group for inode 8193 correctly, then show what the wrong (no −1) formula gives.
Recall Solution
Correct: . Inode 8193 is the first inode of group 1 — index . ✓ Wrong (no −1): — coincidentally right here. Now try inode 8192 (last of group 0): correct ✓; wrong ✗ — off by one group exactly at the boundary. That is where the bug hides.

L3.3
Q: , inodes/group = 8192, inode size = 256 bytes. How many blocks does one group's inode table occupy?
Recall Solution
Bytes of inode table per group: In 4096-byte blocks: So 512 of a group's 32768 blocks are pre-spent on inode records — before any file data exists.
Level 4 — Synthesis
(Combine several rules into one answer.)
L4.1
Q: . A file is 100 KiB. (a) How many 4-KiB data blocks? (b) If it were laid out perfectly contiguously, how many extents minimally describe it? (c) Why is that a win over old indirect pointers?
Recall Solution
(a) bytes. blocks (it divides evenly: ). (b) One extent = "logical blocks → physical blocks ", so 1 extent if fully contiguous. (c) Old ext2/3 would need ~25 individual block pointers (and an indirect block once you exceed the 12 direct slots). Extents replace all of that with one record → smaller inode footprint, fewer reads to map the file. This is the ext4 improvement.
L4.2
Q: Resolve /home/ada/x.txt — list every inode read, in order, and say what each read produces. State why the chain can even start.
Recall Solution
It can start because root is a fixed inode: inode 2.
- Read inode 2 (
/) → its data block is a directory listing → find entryhome→ giveshome's inode #. - Read
home's inode → its data → findada→ givesada's inode #. - Read
ada's inode → its data → findx.txt→ gives the file's inode #. - Read the file's inode → its extents → physical data blocks → the bytes.
Pattern: inode → data (directory) → name lookup → next inode, repeated per path component, then one final inode → extents → data. Each / in the path = one such hop. This is the mechanism Virtual File System exposes uniformly across filesystems.
L4.3
Q: A user runs out of the ability to create files while df shows 40% free space. Diagnose in ext4 terms and give the exact command to confirm.
Recall Solution
Inodes are a separate, fixed pool allocated at mkfs time (see L3.3 — the table is pre-sized). Millions of tiny/empty files can exhaust inodes while data blocks remain free. df shows block usage; the inode pool is invisible to it.
Confirm with:
df -i
If the IUse% column reads 100%, the pool is exhausted — no bytes will help; you'd need to delete files or reformat with more inodes.
Level 5 — Mastery
(Design-level: derive geometry from constraints, reason about edge cases.)
L5.1
Q: Prove that for block size bytes, a block group's size in bytes equals . Then evaluate for and confirm it equals 128 MiB.
Recall Solution
Chain of constraints:
- One block = bytes = bits (8 bits per byte).
- The block bitmap is one block, so it has bits, and one bit ↔ one block. Therefore blocks per group .
- Each block is bytes, so group size bytes. ∎
For : bytes. MiB. ✓ Key insight: the single choice of fixes the entire geometry — bitmap-fits-one-block is the master constraint.
L5.2
Q: , inodes/group = 8192. A 10 GiB disk. Estimate total inode count across the whole filesystem (ignore metadata reserve). Then say what df -i would report as total.
Recall Solution
Groups: groups.
Total inodes inodes.
df -i total ≈ 655,360 (minus reserved inodes 1–10 shown as used). So this disk can hold at most ~655k files no matter how tiny — a hard ceiling set at format time.
L5.3
Q: Degenerate case: what happens to a group's usable data region when a group does carry a superblock+GDT backup versus one that does not? Reason about why ext4 does not put a backup in every group.
Recall Solution
A group carrying a backup spends extra blocks on: 1 superblock copy + the Group Descriptor Table copy. Those blocks are unavailable for file data, so a backup-bearing group has a slightly smaller data region than a plain group.
ext4 (with the sparse_super feature) places backups only in groups numbered , and powers of (e.g. group 3, 9, 25, 49...). Why not all? A backup in every group wastes a lot of space on redundancy that is only needed once for recovery. A handful of well-spread copies is enough for fsck to rebuild — this is the classic redundancy-vs-overhead trade, the same spirit as Journaling (protect just enough metadata, not everything twice).
Recall One-line self-quiz before you leave
Blocks per group formula? ::: (bits in one bitmap block, = block size in bytes).
Group of inode with per group? ::: — subtract 1 for 1-based numbering.
Which gauge shows inode exhaustion? ::: df -i, not df.