From 7241838b4cecefb32bad4698e748fc31d008d94d Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Tue, 20 Aug 2019 20:23:18 -0400 Subject: 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. --- labs/fs1.html | 215 ---------------------------------------------------------- 1 file changed, 215 deletions(-) delete mode 100644 labs/fs1.html (limited to 'labs/fs1.html') 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 @@ - - -Lab: mount/umount - - - - -

Lab: mount/umount

- -

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. - -

Your job is modify xv6 so that your modified kernel passes the - tests in mounttest. You will have to implement two system - calls: mount(char *source, char *target) - and umount(char *target). Mount attaches the device - referenced by source (e.g., /disk1) at the - location specified by target. For - example, mount("/disk1", "/m") will attach disk1 - at the directory /m. After this mount call, users can use - pathnames such as /m/README to read the - file README stored in the root directory - on disk1. Umount removes the attachment. For - example, umount("/m") unmounts disk1 from /m. - -

There are several major challenges in implementing the mount system -calls: - -

- -

The rest of this assignment provides some hints how you might go -about the above challenges. - -

Adding system calls

- -

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 mount. - - -

Adding a second disk

- -

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 0x10002000; modify the macro R to take a disk -number (0, 1,..) and read/write to the memory address for that disk. - -

All functions in virtio_disk.c 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 virtio_disk_init 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). - -

The second disk interrupts at IRQ 2; modify trap.c to receive that -interrupt and virtio_disk_intr with the number of the disk -that generated the interrupt. - -

Modify the file Makefile to tell qemu to provide a second -disk. Define the variable QEMUEXTRA = -drive -file=fs1.img,if=none,format=raw,id=x1 -device -virtio-blk-device,drive=x1,bus=virtio-mmio-bus.1 and -add $(QEMUEXTRA) to the end of QEMUOPTS. - -

Create a second disk image fs1.img. Easiest thing to do - is just copy the file fs.img. You might want to add rules - to the Makefile to make this image and remove it on make - clean. - -

Add to the user program init a call to create a device for the new - disk. For example, add the line mknod("disk1", DISK, 1); to - init.c. This will create an inode of type device in the root - directory with major number DISK and minor number 1. - -

The first argument of the mount system call ("disk1") will - refer to the device you created using mknod above. In your - implementation of the mount system call, - call virtio_disk_init with the minor number as the argument - to initialize the second disk. (We reserve minor number 0 for the - first disk.) - -

Boot xv6, run mounttest, and make sure virtio_disk_init - 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. - -

Modify the logging system

- -

After calling virtio_disk_init, you need to also - call loginit 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., log. changes - to log[n].), similar to generalizing the disk driver to - support two disks. - -

To make xv6 compile, you need to provide a disk number - to begin_op and end_op. 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. - -

Pathname lookup

- -

Modify namex to traverse mount points: when namex - 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., dev), which is initialized and - passed to reads and writes to the driver. dev corresponds - to the minor number for disk devices. - -

Your modified xv6 should be able to pass the first tests in - mounttest (i.e., stat). 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. - -

Even though stat may return correctly, your code is likely - to be incorrect, because in namex - because iunlockput 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 begin_op and end_op to take the - right device. One challenge is that begin_op 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 begin_op passed ilock because that - violates lock ordering in xv6; you should not be - calling begin_op 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.) - -

Once you have implemented a plan for begin_op - and end_op, see if your kernel can pass test0. 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 test0. - -

Run usertests to see if you didn't break anything else. Since you - modified namex and begin/end_op, 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. - -

umount

- -

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 ref > 0. - Furthermore, this test and unmounting should be an atomic - operation. (Hint: lock the inode cache.) Make sure your kernel - passes test1 of mounttest. - -

Test2 of mounttest stresses namex more; if you have done - everything right above, your kernel should pass it. Test3 tests - concurrent mount/unmounts with file creation. - -

crash safety

- -

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. - - - - - -

Optional challenges

- -

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. - -

Support mounts on top of mounts. -- cgit v1.2.3