xv6, line by line
tour 34
Tours34 Path lookup

Tour 34 · File system · about 23 minutes · 15 steps

Path lookup

A program says open("/a/b/c"). The disk has no idea what /a/b/c means. It knows inode numbers and blocks. Somewhere between the two, the kernel must walk from the root directory to a, from a to b, from b to c, reading one directory at a time, while other harts may be creating, deleting and walking through the very same directories.

This tour follows that walk, in namex, for a real path on a fresh disk. You will see skipelem chop the path into names, dirlookup search each directory, and the rule that makes the walk safe on three harts: hold one inode lock at a time. You will see why breaking that rule would deadlock on .., how nameiparent stops one step early for create and unlink, how relative paths start from the current directory, and a check added in this very version of xv6 that refuses to walk through a deleted directory. Without it, the kernel panicked; we reproduce the panic.

Best after: 33. The life of an inode

Who is running where

The machine has three harts. On a fresh boot the user typed mkdir a, mkdir a/b and echo hi > a/b/c (pids 3, 4, 5), and now cat /a/b/c (pid 6). When the tour starts:

Hart What it is doing
0 Idle in its scheduler, or running other users of the same directories
1 Running cat (pid 6): the process this tour follows
2 Idle, or running a process that is changing /a while cat walks through it

The shell (pid 2) is asleep in kwait.

Three harts are running. This tour follows one path through the code, but the machine has three CPUs executing at the same time. Watch the locks held display at the top of each step, and read the Meanwhile, on other harts boxes: they show what the other CPUs could be doing at that very moment.
The route
  1. 1The tree on the disk user/cat.c
  2. 2open hands the string to namei kernel/fs.c
  3. 3Where to start, root or cwd kernel/fs.c
  4. 4skipelem cuts off one name at a time kernel/fs.c
  5. 5Lock the directory, and check that it is one kernel/fs.c
  6. 6dirlookup scans the root for "a" kernel/fs.c
  7. 7Let go of the parent before touching the child kernel/fs.c
  8. 8Why not hold both? Two ways to deadlock kernel/fs.c
  9. 9Down to a, then b: the inode read on the way kernel/fs.c
  10. 10The walk ends, and c comes back unlocked kernel/fs.c
  11. 11The deleted directory, and a panic fixed in this version kernel/fs.c
  12. 12nameiparent stops one step early kernel/fs.c
  13. 13Relative paths start from cwd kernel/sysfile.c
  14. 14Walking while someone else deletes kernel/sysfile.c
  15. 15What a lookup costs, and what it promises kernel/fs.c

Keys: ← → step · Home start