-@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
-periodically write all cached blocks to disk. If you have
-@func{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.
-
-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 the disk contents will be consistent.
-
-@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 FAQ
+Read-ahead is only really useful when done asynchronously. That means,
+if a process requests disk block 1 from the file, it should block until disk
+block 1 is read in, but once that read is complete, control should
+return to the process immediately. The read-ahead request for disk
+block 2 should be handled asynchronously, in the background.
+
+@strong{We recommend integrating the cache into your design early.} In
+the past, many groups have tried to tack the cache onto a design late in
+the design process. This is very difficult. These groups have often
+turned in projects that failed most or all of the tests.
+
+@node File System Synchronization
+@subsection Synchronization
+
+The provided file system requires external synchronization, that is,
+callers must ensure that only one thread can be running in the file
+system code at once. Your submission must adopt a finer-grained
+synchronization strategy that does not require external synchronization.
+To the extent possible, operations on independent entities should be
+independent, so that they do not need to wait on each other.
+
+Operations on different cache blocks must be independent. In
+particular, when I/O is required on a particular block, operations on
+other blocks that do not require I/O should proceed without having to
+wait for the I/O to complete.
+
+Multiple processes must be able to access a single file at once.
+Multiple reads of a single file must be able to complete without
+waiting for one another. When writing to a file does not extend the
+file, multiple processes should also be able to write a single file at
+once. A read of a file by one process when the file is being written by
+another process is allowed to show that none, all, or part of the write
+has completed. (However, after the @code{write} system call returns to
+its caller, all subsequent readers must see the change.) Similarly,
+when two processes simultaneously write to the same part of a file,
+their data may be interleaved.
+
+On the other hand, extending a file and writing data into the new
+section must be atomic. Suppose processes A and B both have a given
+file open and both are positioned at end-of-file. If A reads and B
+writes the file at the same time, A may read all, part, or none of what
+B writes. However, A may not read data other than what B writes, e.g.@:
+if B's data is all nonzero bytes, A is not allowed to see any zeros.
+
+Operations on different directories should take place concurrently.
+Operations on the same directory may wait for one another.
+
+@node Project 4 FAQ