Lab fs: Device files & symbolic links

Your task is to extend the xv6 filesystem with support for special device files and for symbolic links.

File system in the xv6 book

Before writing code, you should read Chapter 8, File system from the xv6 book and study the corresponding code.

To start the lab, update your repository and create a new branch for your solution:

$ git fetch origin
$ git checkout -b fs origin/xv6-21au
$ make clean

Device files

In this part of the lab you will extend xv6 by adding support for four different kinds of device files. These files appear as regular files in the file system hierarchy but are implemented by functions in the kernel instead of being backed by a physical disk.

$ echo hello > /dev/null
$ cat /dev/null
$
$ echo hello > /dev/zero
$ cat /dev/zero
[Never terminates]
$ cat /dev/random
[Infinite stream of random bytes]
$ cat /dev/uptime
19
$ cat /dev/uptime
45
$

When you have implemented these files, you can run the tests in xv6 with specialtest. Your solution must modify init to create the speical files using mknod; the test assumes they already exist. Your solution is complete when the tests produce the following output (and usertests still succeeds):

$ specialtest

START: test /dev/null
reading from /dev/null..
writing to /dev/null..
reading from /dev/null again..
SUCCESS: test /dev/null

START: test /dev/zero
writing to /dev/zero..
reading from /dev/zero..
SUCCESS: test /dev/zero

START: test /dev/uptime
Reading from /dev/uptime..
Reading from /dev/uptime again..
SUCCESS: test /dev/uptime

START: test /dev/random
Opening /dev/random..
reading from /dev/random four times..
SUCCESS: test /dev/random
$

Here’s one reasonable plan of attack.

Challenge: procfs

These device files are limited in that they can only be used to create special files, not directories. Add support for procfs to xv6 to get around this limitation.

The second part of this lab is to add support for symbolic links to xv6. Symbolic links (or soft links) refer to a linked file by pathname; when a symbolic link is opened, the kernel follows the link to the referred file. Symbolic links resemble hard links, but hard links are restricted to pointing to file on the same disk, while symbolic links can cross disk devices. Although xv6 doesn’t support multiple devices, implementing this system call is a good exercise to understand how pathname lookup works.

For this part of the lab, you will implement a the int symlink(const char *target, const char *linkpath) system call, which creates a new symbolic link at linkpath that refers to file named by target. See the POSIX specification on symlink for further information.

To test, add symlinktest to the Makefile and run it. Your solution is complete when the tests produce the following output (and usertests still succeeds):

$ symlinktest

START: test symlinks
Creating a
Linking b -> a
Writing to a
Reading from b
Removing a
Linking a -> b
Attempting to open b (cycle)
Symlinking c to nonexistent file
Creating symlink chain 1->2->3->4
SUCCESS: test symlinks
$

Here’s one reasonable plan of attack.

Challenge: O_NOFOLLOW

Add support for a new flag O_NOFOLLOW that can be used with the open system call. When a process specifies O_NOFOLLOW in the flags to open, open should open the symbolic link (and not follow the symbolic link).

Challenge: symbolic links to directories

Add support for symbolic links to directories. This is tricky because the middle components of a path may refer to a symbolic link; you must modify namex to deal with this possibility.

Challenge: rename

Implement the rename system call. Note that it can be tricky to handle all corner cases, for example, when the target already exists or when renaming a directory. Refer to the POSIX specification of rename for details.

This completes the lab. In the lab directory, commit your changes, type make tarball, and submit the tarball through Canvas.