xv6, line by line
lab 23
Lab 2323 Symbolic links

Lab 23 · reveal · 16 steps · 7 commits

Symbolic links: the reference solution

In this tree a name in a directory is a hard link: a struct dirent holding an inode number. Two names can share one inode, but only inside one file system, never for a directory, and the inode stays alive while any name points at it. A symbolic link is a different idea: a small file whose content is a path name, which open replaces by the thing that path names. It may point at a directory, at a name that does not exist yet, or at another link.

You add a fourth inode type, a symlink(target, path) system call, and following in open. The code is short. The questions are not. Which system calls should follow a link, and what happens to the ones that do not? Where in the inode does the target go, and inside which transaction? A link can name itself, or its own directory: what may the kernel hold while it looks a target up, given the order in which namex takes inode locks? What stops a cycle of links, and what does the machine look like if nothing does? A relative target like f: relative to what?

The reference solution is seven small commits. With it, ln -s f d/l makes a link whose creation logs a handful of disk blocks, and opening a file through one link costs about twice as much as opening it directly, because following is a second path lookup.

Each step shows one change on the branch ext/23-symlink, the code around it, and the state of the machine when that code runs.

The route
  1. 1A fourth kind of inode kernel/stat.h
  2. 2A flag for the link itself, and a bound kernel/fcntl.h
  3. 3The plumbing of a new system call kernel/syscall.c
  4. 4sys_symlink: arguments, then one transaction kernel/sysfile.c
  5. 5Parent, then a new inode, both locked kernel/sysfile.c
  6. 6The target first, the name last kernel/sysfile.c
  7. 7follow: a loop, with a bound kernel/sysfile.c
  8. 8Let go of the link, then look up its target kernel/sysfile.c
  9. 9Type checks move below the follow kernel/sysfile.c
  10. 10resolve: a relative target, from the link's directory kernel/sysfile.c
  11. 11follow keeps the path up to date kernel/sysfile.c
  12. 12O_CREATE on an existing link kernel/sysfile.c
  13. 13ln -s user/ln.c
  14. 14Testing the limits exactly user/symlinktest.c
  15. 15Three harts, four links, chains and cycles user/symlinktest.c
  16. 16unlink needs no change at all kernel/sysfile.c

Keys: ← → step · Home start