-prepared for interactions with all previous parts (as usual).
-
-@node Problem 4-1 Large Files
-@section Problem 4-1: Large Files
-
-Modify the file system to allow the maximum size of a file to be as
-large as the disk. You can assume that the disk will not be larger
-than 8 MB. In the basic file system, each file is limited to a file
-size of just under 64 kB. Each file has a header (@code{struct
-filehdr}) that is a table of direct pointers to the disk blocks for
-that file. Since the header is stored in one disk sector, the maximum
-size of a file is limited by the number of pointers that will fit in
-one disk sector. Increasing the limit to 8 MB will require you to
-implement doubly-indirect blocks.
-
-@node Problem 4-2 File Growth
-@section Problem 4-2: File Growth
-
-Implement extensible files. In the basic file system, the file size
-is specified when the file is created. One advantage of this is that
-the FileHeader data structure, once created, never changes. In UNIX
-and most other file systems, a file is initially created with size 0
-and is then expanded every time a write is made off the end of the
-file. Modify the file system to allow this. As one test case, allow
-the root directory file to expand beyond its current limit of ten
-files. Make sure that concurrent accesses to the file header remain
-properly synchronized.
-
-@node Problem 4-3 Subdirectories
-@section Problem 4-3: Subdirectories
-
-Implement a hierarchical name space. In the basic file system, all
-files live in a single directory. Modify this to allow directories to
-point to either files or other directories. To do this, you will need
-to implement routines that parse path names into a sequence of
-directories, as well as routines that change the current working
-directory and that list the contents of the current directory. For
-performance, allow concurrent updates to different directories, but
-use mutual exclusion to ensure that updates to the same directory are
-performed atomically (for example, to ensure that a file is deleted
-only once).
-
-Make sure that directories can expand beyond their original size just
-as any other file can.
-
-To take advantage of hierarchical name spaces in user programs,
-provide the following syscalls:
-
-@table @code
-@item SYS_chdir
-@itemx bool chdir (const char *@var{dir})
-Attempts to change the current working directory of the process to
-@var{dir}, which may be either relative or absolute. Returns true if
-successful, false on failure.
-
-@item SYS_mkdir
-@itemx bool mkdir (const char *dir)
-Attempts to create the directory named @var{dir}, which may be either
-relative or absolute. Returns true if successful, false on failure.
-
-@item SYS_lsdir
-@itemx void lsdir (void)
-Prints a list of files in the current directory to @code{stdout}, one
-per line.
-@end table
-
-Also write the @command{ls} and @command{mkdir} user programs. This
-is straightforward once the above syscalls are implemented. If Unix,
-these are programs rather than built-in shell commands, but
-@command{cd} is a shell command. (Why?)
-
-@node Problem 4-4 Buffer Cache
-@section Problem 4-4: Buffer Cache
-
-Modify the file system to keep a cache of file blocks. When a request
-is made to read or write a block, check to see if it is stored in the
-cache, and if so, fetch it immediately from the cache without going to
-disk. (Otherwise, fetch the block from disk into cache, evicting an
-older entry if necessary.) You are limited to a cache no greater than
-64 sectors in size. Be sure to choose an intelligent cache
-replacement algorithm. Experiment to see what combination of use,
-dirty, and other information results in the best performance, as
-measured by the number of disk accesses. (For example, metadata is
-generally more valuable to cache than data.) Document your
-replacement algoritm in your design document.
-
-In addition to the basic file caching scheme, your implementation
-should also include the following enhancements:
-
-@table @b
-@item write-behind:
-Instead of always immediately writing modified data to disk, dirty
-blocks can be kept in the cache and written out sometime later. Your
-buffer cache should write behind whenever a block is evicted from the
-cache.
-
-@item read-ahead:
-Your buffer cache should automatically fetch the next block of a file
-into the cache when one block of a file is read, in case that block is
-about to be read.
-@end table
-
-For each of these three optimizations, design a file I/O workload that
-is likely to benefit from the enhancement, explain why you expect it
-to perform better than on the original file system implementation, and
-demonstrate the performance improvement.
-
-Note that write-behind makes your filesystem more fragile in the face
-of crashes. Therefore, you should implement some manner to
-periodically write all cached blocks to disk. If you have
-@code{timer_sleep()} from the first project working, this is an
-excellent application for it.
-
-Likewise, read-ahead is only really useful when done asynchronously.
-That is, if a process wants disk block 1 from the file, it needs to
-block until disk block 1 is read in, but once that read is complete,
-control should return to the process immediately while the read
-request for disk block 2 is handled asynchronously. In other words,
-the process will block to wait for disk block 1, but should not block
-waiting for disk block 2.
-
-FIXME
-When you're implementing this, please make sure you have a scheme for
-making any read-ahead and write-behind threads halt when Pintos is
-``done'' (when the user program has completed, etc), so that Pintos
-will halt normally and print its various statistics.
-
-@node File System Design Document Requirements
-@section Design Document Requirements
-
-As always, submit a design document file summarizing your design. Be
-sure to cover the following points :
-
-@itemize @bullet
-@item
-How did you structure your inodes? How many blocks did you access
-directly, via single-indirection, and/or via double-indirection? Why?
-
-@item
-How did you structure your buffer cache? How did you perform a lookup
-in the cache? How did you choose elements to evict from the cache?
-
-@item
-How and when did you flush the cache?
-@end itemize
-
-@node File System FAQs
-@section FAQ
-
-@enumerate 1
-@item
-@b{What extra credit opportunities are available for this assignment?}
-
-@itemize @bullet
-@item
-We'll give out extra credit to groups that implement Unix-style
-support for @file{.} and @file{..} in relative paths in their projects.
-
-@item
-We'll give some extra credit if you submit with VM enabled. If you do
-this, make sure you show us that you can run multiple programs
-concurrently. A particularly good demonstration is running
-@file{capitalize} (with a reduced words file that fits comfortably on
-your disk, of course). So submit a file system disk that contains a
-VM-heavy program like @file{capitalize}, so we can try it out. And also
-include the results in your test case file.
-
-We feel that you will be much more satisfied with your cs140 ``final
-product'' if you can get your VM working with your file system. It's
-also a great stress test for your FS, but obviously you have to be
-pretty confident with your VM if you're going to submit this extra
-credit, since you'll still lose points for failing FS-related tests,
-even if the problem is in your VM code.
-
+prepared for interactions with all previous parts.
+
+@node Testing File System Persistence
+@subsection Testing File System Persistence
+
+By now, you should be familiar with the basic process of running the
+Pintos tests. @xref{Testing}, for review, if necessary.
+
+Until now, each test invoked Pintos just once. However, an important
+purpose of a file system is to ensure that data remains accessible from
+one boot to another. Thus, the tests that are part of the file system
+project invoke Pintos a second time. The second run combines all the
+files and directories in the file system into a single file, then copies
+that file out of the Pintos file system into the host (Unix) file
+system.
+
+The grading scripts check the file system's correctness based on the
+contents of the file copied out in the second run. This means that your
+project will not pass any of the extended file system tests until the
+file system is implemented well enough to support @command{tar}, the
+Pintos user program that produces the file that is copied out. The
+@command{tar} program is fairly demanding (it requires both extensible
+file and subdirectory support), so this will take some work. Until
+then, you can ignore errors from @command{make check} regarding the
+extracted file system.
+
+Incidentally, as you may have surmised, the file format used for copying
+out the file system contents is the standard Unix ``tar'' format. You
+can use the Unix @command{tar} program to examine them. The tar file
+for test @var{t} is named @file{@var{t}.tar}.
+
+@node Project 4 Suggested Order of Implementation
+@section Suggested Order of Implementation
+
+To make your job easier, we suggest implementing the parts of this
+project in the following order:
+
+@enumerate