ยง40.4โ€“40.6Directories, Free Space, and Access Paths

Part III OSTEP pp. 501โ€“505 ยท ~6 min read

  • directory entry
  • pre-allocation
  • access path

Now that files and inodes are on disk, we fill in directories, free-space tracking, and the access paths that reads and writes actually follow.

40.4 Directory Organization

A directory is stored simply: its data blocks hold a list of directory entries, each a (name โ†’ inode number) pair with a record length (reclen) and string length (strlen):

The on-disk contents of directory `dir` (inode 5) holding foo, bar, and a long-named file. Each entry maps a name to an inode number, with a record length and string length.
inumreclenstrlenname
.5122.
..2123..
foo12124foo
bar13124bar
long243628foobar_is_a_pretty_longname
Dotted-underlined cells have explanations โ€” click one.

Every directory has . (itself) and .. (its parent). Deleting a file leaves a gap โ€” often marked with a reserved inode number (like 0) โ€” and the reclen lets a later, smaller entry reuse that space. Crucially, a directory is just a file: it has an inode (with its type field set to โ€œdirectoryโ€) whose data blocks hold these entries. So the on-disk structure needs nothing new. (Other designs are possible โ€” XFS stores directories as B-trees to speed up lookups; FAT uses linked lists and has no inodes at all.)

40.5 Free Space Management

To allocate a new inode or data block, the FS consults a bitmap. Creating a file, for instance, means scanning the inode bitmap for a free slot (a 0), marking it used (1), and writing the updated bitmap back to disk:

inode bitmap111101001000โ†‘ found a free 0 โ†’ set to 1 (allocated)

A refinement is pre-allocation : ext2/ext3 look for a run of, say, 8 consecutive free blocks when a file is created, so part of the file lands contiguously on disk and is faster to read and write later.

40.6 Access Paths: Reading and Writing

The second half of understanding a file system is the access path โ€” which structures get read and written for each operation. Assume the FS is mounted (superblock in memory) but inodes and directories are still on disk. Watch what open("/foo/bar") then reading it actually does:

Reading /foo/bar: open() walks the path from the root, reading an inode and directory data at each level; then each read() consults the inode, reads a data block, and writes the inode (access time). Note: no bitmap is ever touched.
inode table
directory data
file data
open("/foo/bar"): traverse the path
read() the first block
read() blocks 1 and 2 โ€” same rhythm
step 1 / 10 ยท time flows downward

The root's i-number is "well known" (2 in most UNIX file systems), so the FS can find it with no parent to consult.

Aside: Reads Donโ€™t Touch the Allocation Structures

A common confusion: reading a file does not consult the bitmaps. The inode already points at the fileโ€™s blocks, so thereโ€™s nothing to allocate and nothing to check. Bitmaps are read/written only when allocating or freeing.

Writing is worse, because it may allocate. Each allocating write turns into five I/Os, and creating a file โ€” which must allocate an inode and update its directory โ€” costs around ten:

The I/O cost of the access paths โ€” and why even simple operations are expensive.
operationdisk I/Oswhat they are
openopen a fileโˆ path lengthread inode + data for root, then foo, then read bar's inode
readread one block3read inode (locate block) ยท read the data block ยท write inode (access time)
awriteallocating write (one block)5read + write the data bitmap ยท read + write the inode ยท write the data block
createcreate a file~10path traversal + inode allocation + directory update
Dotted-underlined cells have explanations โ€” click one.

The Crux: How To Reduce File System I/O Costs

Even opening, reading, or writing a single file triggers a flurry of I/Os scattered across the disk. What can a file system do to cut these costs? (The next section โ€” caching and buffering โ€” is the first answer.)

Check yourself: directories, free space, access paths

1.How is a directory stored in vsfs?

2.What is the record length (reclen) in a directory entry for?

3.When are the allocation bitmaps consulted during a plain file READ?

4.Why is the I/O cost of open() proportional to the pathname length?

5.Why does a single allocating write cost 5 I/Os?

6.What is pre-allocation, and why do it?

6 questions