From "/home/r/file.txt" to the Actual Bytes on Disk
The Problem
You have a string: "/home/r/file.txt". You want the bytes of that file. Between your string and those bytes sit at minimum 4 disk reads and a chain of integer lookups.
Step-by-Step Walk (ext4, 4096-byte blocks, 256-byte metadata records)
The filesystem reserves record #2 for the root. To find it on disk:
group = (2 - 1) / inodes_per_group = 1 / 8192 = 0 (group 0)
index = (2 - 1) % inodes_per_group = 1
byte_offset_in_table = 1 * 256 = 256
The metadata-record table for group 0 starts at some block B
(read from the group descriptor table).
Read block B, seek to offset 256 within it → that's the root's record.
The root's metadata record has an extent array. The first extent says: file block 0 maps to physical block P. Read block P from disk. It contains a name-to-number table:
Offset Record-# Name-len Name
0x00 2 1 "."
0x0C 2 2 ".."
0x18 131073 4 "home" ← found it! record number = 131073
0x28 393217 3 "usr"
...
Each entry is: [4-byte record number] [2-byte entry length] [1-byte name length] [1-byte file type] [name bytes].
group = (131073 - 1) / 8192 = 16 (group 16)
index = (131073 - 1) % 8192 = 0
byte_offset = 0 * 256 = 0
Read the metadata-record table block for group 16.
Read the data blocks of record #131073.
Search the name-to-number table for "r".
Found: record number = 131074
group = (131074 - 1) / 8192 = 16
index = (131074 - 1) % 8192 = 1
byte_offset = 1 * 256 = 256
Read that record. Read its data blocks.
Search name-to-number table for "file.txt".
Found: record number = 131080
This record is NOT a directory, it's a regular file.
Fields we care about:
i_size = 8500 (file is 8500 bytes)
i_block[0..3] holds extent records:
extent 0: logical block 0, physical block 525000, length 3
Read physical blocks 525000, 525001, 525002 from disk.
Concatenate. Trim to 8500 bytes. Done.
Disk Reads Counted
Read 1: root metadata record (#2)
Read 2: root's data block (name-to-number table of "/")
Read 3: record #131073 (the "home" directory metadata)
Read 4: "home"'s data block (name-to-number table)
Read 5: record #131074 ("r" directory metadata)
Read 6: "r"'s data block
Read 7: record #131080 ("file.txt" metadata)
Read 8: file.txt's data blocks (3 blocks)
Total: 8 disk reads minimum for /home/r/file.txt
Why the In-Memory Name Cache Matters
The kernel maintains an in-memory table mapping (parent_record_number, name_string) → child_record_number. After the first walk, the pair (2, "home") → 131073 is cached. Next access skips the disk entirely for that component.
Cache hit rate for "/" → ~100% (always cached)
Cache hit rate for "/home" → ~99% (almost always cached)
Cache hit rate for "/home/r" → ~95%
Cache hit rate for deep paths → varies by access pattern
ext4 Name-to-Number Table Entry Layout (On Disk)
Bytes [0..3]: 4-byte record number (little-endian)
Bytes [4..5]: 2-byte total entry length (for padding/alignment)
Byte [6]: 1-byte name length
Byte [7]: 1-byte file type (1=regular, 2=directory, 7=symlink)
Bytes [8..N]: name characters (NOT null-terminated on disk)
Minimum entry size: 8 + 1 = 9 bytes, rounded to 4-byte boundary = 12 bytes. Maximum name: 255 bytes.