diff options
author | Frans Kaashoek <[email protected]> | 2019-08-20 20:23:18 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2019-08-20 20:23:18 -0400 |
commit | 7241838b4cecefb32bad4698e748fc31d008d94d (patch) | |
tree | 7b52f0c55604ee8801d2a6edfe46c4d931e35273 /labs/fs1.html | |
parent | c612d452fdb03080c77517f6c1b32b8d11c6c40a (diff) | |
download | xv6-labs-7241838b4cecefb32bad4698e748fc31d008d94d.tar.gz xv6-labs-7241838b4cecefb32bad4698e748fc31d008d94d.tar.bz2 xv6-labs-7241838b4cecefb32bad4698e748fc31d008d94d.zip |
Move labs into 6.828 repo. The lab text isn't dependent on specific
xv6 code. Lab submission instructions etc. are likely going to be more
MIT 6.828 specific.
Diffstat (limited to 'labs/fs1.html')
-rw-r--r-- | labs/fs1.html | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/labs/fs1.html b/labs/fs1.html deleted file mode 100644 index 45d3e0c..0000000 --- a/labs/fs1.html +++ /dev/null @@ -1,215 +0,0 @@ -<html> -<head> -<title>Lab: mount/umount</title> -<link rel="stylesheet" href="homework.css" type="text/css" /> -</head> -<body> - -<h1>Lab: mount/umount</h1> - -<p>In this lab you will add support for mounting/unmounting of file -systems to xv6. This lab will expose you to many parts of the xv6 -file system, including pathname lookup, inodes, logging/recovery, disk -driver, concurrency, etc. - -<p>Your job is modify xv6 so that your modified kernel passes the - tests in mounttest. You will have to implement two system - calls: <tt>mount(char *source, char *target)</tt> - and <tt>umount(char *target)</tt>. Mount attaches the device - referenced by <tt>source</tt> (e.g., <tt>/disk1</tt>) at the - location specified by <tt>target</tt>. For - example, <tt>mount("/disk1", "/m")</tt> will attach <tt>disk1</tt> - at the directory <tt>/m</tt>. After this mount call, users can use - pathnames such as <tt>/m/README</tt> to read the - file <tt>README</tt> stored in the root directory - on <tt>disk1</tt>. <tt>Umount</tt> removes the attachment. For - example, <tt>umount("/m")</tt> unmounts disk1 from <tt>/m</tt>. - -<p>There are several major challenges in implementing the mount system -calls: - - <ul> - - <li>Adding the actual system calls so that user programs can call - them. This is similar to previous labs in which you added - systems calls xv6. - - <li>Supporting several disks. You will have generalize to - virtio_disk.c to support at least two disks. - - <li>Logging file system modifications to the right disk. xv6 - assumes there is only disk and file system calls typically start - with <tt>begin_op</tt> and end with <tt>end_op</tt>, logging all - modifications between these two calls to the log on the one - disk. With mount, modifications to the file system on the - second disk must be logged to the second disk. - - <li>Modifying pathname lookup (<tt>namex</tt>) so that when a - lookup cross a mount point, it continues at the root inode of - the attached disk. - - </ul> - -<p>The rest of this assignment provides some hints how you might go -about the above challenges. - -<h2>Adding system calls</h2> - -<p>Add the stubs for the two systems calls to xv6 so that you can -compile mounttest and add two empty functions for the two system calls -to sysfile.c. Run mounttest and it will fail on the first call -to <tt>mount</tt>. - - -<h2>Adding a second disk</h2> - -<p>To be able to mount another disk, you need to extend xv6 to support -at least two disks. Modify virtio_disk.c to support an array of two -disks instead of a single disk. The address of the second disk -is <tt>0x10002000</tt>; modify the macro <tt>R</tt> to take a disk -number (0, 1,..) and read/write to the memory address for that disk. - -<p>All functions in <tt>virtio_disk.c</tt> need to take the disk -number as an argument to update the state of the disk that is -read/written to or to receive an interrupt from the disk. -Modify <tt>virtio_disk_init</tt> to take a disk number as an argument -and update is to that it initializes that disk. Similar, go through -the other functions; make these changes should be most mechanical -(i.e., text substitutions). - -<p>The second disk interrupts at IRQ 2; modify trap.c to receive that -interrupt and <tt>virtio_disk_intr</tt> with the number of the disk -that generated the interrupt. - -<p>Modify the file Makefile to tell qemu to provide a second -disk. Define the variable <tt>QEMUEXTRA = -drive -file=fs1.img,if=none,format=raw,id=x1 -device -virtio-blk-device,drive=x1,bus=virtio-mmio-bus.1</tt> and -add <tt>$(QEMUEXTRA)</tt> to the end of <tt>QEMUOPTS</tt>. - -<p>Create a second disk image <tt>fs1.img</tt>. Easiest thing to do - is just copy the file <tt>fs.img</tt>. You might want to add rules - to the Makefile to make this image and remove it on <tt>make - clean</tt>. - -<p>Add to the user program init a call to create a device for the new - disk. For example, add the line <tt>mknod("disk1", DISK, 1);</tt> to - init.c. This will create an inode of type device in the root - directory with major number <tt>DISK</tt> and minor number 1. - -<p>The first argument of the <tt>mount</tt> system call ("disk1") will - refer to the device you created using <tt>mknod</tt> above. In your - implementation of the mount system call, - call <tt>virtio_disk_init</tt> with the minor number as the argument - to initialize the second disk. (We reserve minor number 0 for the - first disk.) - -<p>Boot xv6, run mounttest, and make sure <tt>virtio_disk_init</tt> - gets called (e.g., add print statement). You won't know if your - changes are correct, but your code should compile and invoke the - driver for the second disk. - -<h2>Modify the logging system</h2> - -<p>After calling <tt>virtio_disk_init</tt>, you need to also - call <tt>loginit</tt> to initialize the logging system for the - second disk (and restore the second disk if a power failure happened - while modifying the second disk). Generalize the logging system to - support to two logs, one on disk 0 and one disk 1. These changes - are mostly mechanical (e.g., <tt>log.</tt> changes - to <tt>log[n].</tt>), similar to generalizing the disk driver to - support two disks. - -<p>To make xv6 compile, you need to provide a disk number - to <tt>begin_op</tt> and <tt>end_op</tt>. It will be a challenge to - figure out what the right value is; for now just specify the first - disk (i.e., 0). This isn't correct, since modifications to the - second disk should be logged on the second disk, but we have no way - yet to read/write the second disk. Come back to this later when you - have a better idea how things will fit together, but make sure that - xv6 compiles and still runs. - -<h2>Pathname lookup</h2> - -<p>Modify <tt>namex</tt> to traverse mount points: when <tt>namex</tt> - sees an inode to which a file system is attached, it should traverse - to the root inode of that file system. Hint: modify the in-memory - inode in file.h to keep some additional state, and initialize that - state in the mount system call. Note that the inode already has a - field for disk number (i.e., <tt>dev</tt>), which is initialized and - passed to reads and writes to the driver. <tt>dev</tt> corresponds - to the minor number for disk devices. - -<p>Your modified xv6 should be able to pass the first tests in - mounttest (i.e., <tt>stat</tt>). This is likely to be challenging, - however, because now your kernel will be reading from the second - disk for the first time, and you may run into many issues. - -<p>Even though <tt>stat</tt> may return correctly, your code is likely - to be incorrect, because in <tt>namex</tt> - because <tt>iunlockput</tt> may modify the second disk (e.g., if - another process removes the file or directory) and those - modifications must be written to the second disk. Your job is to - fix the calls to <tt>begin_op</tt> and <tt>end_op</tt> to take the - right device. One challenge is that <tt>begin_op</tt> is called at - the beginning of a system call but then you don't know the device - that will be involved; you will have to postpone this call until you - know which inode is involved (which tells you will which device is - involved). Another challenge is that you cannot postpone - calling <tt>begin_op</tt> passed <tt>ilock</tt> because that - violates lock ordering in xv6; you should not be - calling <tt>begin_op</tt> while holding locks on inodes. (The log - system allows a few systems calls to run; if a system call that - holds an inode lock isn't admitted and one of the admitted system - calls needs that inode to complete, then xv6 will deadlock.) - -<p>Once you have implemented a plan for <tt>begin_op</tt> - and <tt>end_op</tt>, see if your kernel can pass <tt>test0</tt>. It - is likely that you will have to modify your implementation of the - mount system call to handle several corner cases. See the tests - in <tt>test0</tt>. - -<p>Run usertests to see if you didn't break anything else. Since you - modified <tt>namex</tt> and <tt>begin/end_op</tt>, which are at the - core of the xv6 file system, you might have introduced bugs, perhaps - including deadlocks. Deadlocks manifest themselves as no output - being produced because all processes are sleeping (hit ctrl-p a few - times). Your kernel might also suffer kernel panics, because your - changes violate invariants. You may have to iterate a few times to - get a good design and implementation. - -<h2>umount</h2> - -<p>Once your kernel passes usertests and test0 of mounttest, implement - umount. The main challenge is that umount of a file system should - fail if the file system is still in use; that is, if there is an - inode on the mounted device that has a <tt>ref > 0</tt>. - Furthermore, this test and unmounting should be an atomic - operation. (Hint: lock the inode cache.) Make sure your kernel - passes test1 of mounttest. - -<p>Test2 of mounttest stresses <tt>namex</tt> more; if you have done - everything right above, your kernel should pass it. Test3 tests - concurrent mount/unmounts with file creation. - -<h2>crash safety</h2> - -<p>One of the main goals of the file system is to provide crash - safety: if there is a power failure during a file system operation, - xv6 should recover correctly. It is difficult to introduce power - failure at the critical steps of logging; instead, we added a system - call that causes a kernel panic after committing an operation but - before installing the operation. Test4 with crashtest tests if your - xv6 recovers the mounted disk correctly. - - -</body> -</html> - -<h2>Optional challenges</h2> - -<p>Modify xv6 so that init mounts the first disk on the root inode. - This will allow you to remove some code specific for the first disk - from the kernel. - -<p>Support mounts on top of mounts. |