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