Assignment 4. File Systems
Introduction
The multiprogramming and virtual memory assignments made use
of the Nachos file system.
The fourth phase of Nachos is to actually build this file system.
As in the first two assignments, we give you some of the code
you need; your job is to complete the file system and enhance it.
The first step is to read and understand the partial file system
we have written for you.
Run the program `nachos -f -cp test/small small' for a simple test case
of our code -- `-f' formats the emulated physical disk, and `-cp'
copies the UNIX file `test/small' onto that disk.
The files to focus on are:
Our file system has a UNIX-like interface, so you may also wish to
read the UNIX man pages for creat, open, close, read, write, lseek,
and unlink (e.g., type ``man creat''). Our file system has calls that
are similar (but not identical) to these; the file system
translates these calls into physical disk operations. One major
difference is that our file system is implemented in C++. Create
(like UNIX creat), Open (open), and Remove (unlink) are defined on the
FileSystem object, since they involve manipulating file names and
directories. FileSystem::Open returns a pointer to an OpenFile
object, which is used for direct file operations such as Seek (lseek),
Read (read), Write (write). An open file is ``closed'' by deleting
the OpenFile object.
Many of the data structures in our file system are stored both in
memory and on disk. To provide some uniformity, all these data
structures have a ``FetchFrom'' procedure that reads the data off disk
and into memory, and a ``WriteBack'' procedure that stores the data
back to disk. Note that the in-memory and on-disk representations do
not have to be identical.
While our code implements all the major pieces of a file system, it
has some limitations. Your job will be to fix these limitations.
Keep in mind that there are, of course, interactions between the
various parts of this assignment.
Problem 1
Complete the basic file system by adding synchronization to
allow multiple threads to use file system concurrently. Currently,
the file system code assumes it is accessed by a single thread at a time.
In addition to ensuring that internal
data structures are not corrupted, your modified file system must
observe the following constraints (these are the same as in UNIX):
Hint: to do this part, you will probably find that you need to maintain
a table of open files.
Problem 2
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 routines to parse path names into
the sequence of directories where to find the file.
You will also need to implement routines to change the
current working directory (cf. the UNIX `cd' command) and to
print 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).
To take advantage of hierarchical name spaces in user programs, you
will need to provide the following system calls:
You should write the ls and mkdir user programs
based on these system calls (it should be very trivial).
Problem 3
Modify the file system to allow the maximum size of a file to be as large
as the disk (128Kbytes). In the basic file system, each file is limited
to a file size of just under 4Kbytes. Each file has a header
(class FileHeader) 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 128KBytes will probably
but not necessarily require you to implement doubly indirect blocks.
Problem 4 (Extra Credit)
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 directory file to expand beyond its current limit
of ten files. In doing this part, be careful that concurrent
accesses to the file header remain properly synchronized.