| Computer Science Dept. | School of Engineering | UC Santa Cruz |
|
Home | Syllabus
| Schedule | Grades
| Feedback Homework: 1 2 3 4 5 | Projects: 1 2 3 4 |
CMPS 111: Introduction to Operating Systems (Winter 2003) |
Assigned: 4 March 2003
Design due: Sunday, March 9th at 11:59 PM
Code due: Friday, March 14th at 11:59 PM (automatic extension
to Sunday, March 16th at 11:59 PM)
The basic rules and project information are the same for this assignment as they were for the second assignment: you may work with a single project partner (i.e., a group of two people doing a single project). The details of this arrangement are the same as the were for Project #2.
As with other projects, the following suggestions apply:
Unlike previous programs, you may not hand this project in late (past March 16th) because we need to have grades done by the end of that week. Late submissions would not give us time to get project grading done in time.
The goal for this project is to implement a simple file system in DLXOS. The file system should have the following features:
First, please make sure you have the latest version of dlxos.tgz. The OS hasn't changed from Project #3, so you can continue to use the code you've been working on. If you've had trouble getting things to work, you may get a clean copy of the OS (from the usual DLXOS locations) if you prefer.
Your file system calls will be integrated into DLXOS in filesys.c. There are routines called FsDlxRead(), and so on for the other calls you need to implement. You need to modify these calls to use the file system you are designing. Your routines will automatically be called when you call FsOpen() with a filename that starts with "dlx:". For example, calling FsOpen() on the file "dlx:/foo" will result in FsDlxOpen() being called with the file /foo. Other calls (except for FsDelete()) are switched automatically based on the file ID set in FsOpen(), which remembers which file system (Unix or DLXOS) the file was opened in.
For this assignment, you'll be reading and writing blocks from a file called (by default) dlxdisk (you should allow its name to be supplied by the -B argument passed to the OS) using the normal file system calls from within DLXOS (open() , read(), write(), etc.). You should treat the dlxdisk file as a "raw disk" on which to build your file system. Your OS need not initialize the disk; you may write a regular program (running in Unix) to set up any initial data structures on dlxdisk that your OS might need. Your disk should be persistent if you shut down DLXOS and restart it, DLXOS should still be able to use the file system with all of the changes that the previous run made to the file system (creates, writes, deletes, etc.).
File blocks should be 1KB (1024 bytes) long. This means that a read() call to read block blocknum from the DLXOS disk looks like this:
#define DLX_DISK_BLOCKSIZE 1024
unsigned char buf[DLX_DISK_BLOCKSIZE];
lseek (dlxdiskfd, blocknum * DLX_DISK_BLOCKSIZE, 0);
nbytes = read(dlxdiskfd, buf, DLX_DISK_BLOCKSIZE);
Write calls look about the same.
You'll probably need to have a "superblock" in your file system that contains some basic information: the size of the file system, the location and length of the FAT, and the first block in the directory. You should read this in when the OS starts up and use the information to configure the file system in the OS.
The superblock needs to be in a fixed location regardless of the size of the file system. We recommend block 0 of the disk—every disk must have a block 0.
Your file system will use a file allocation table to keep track of disk blocks. Your disk will have a maximum of 64K blocks, making the maximum file system size 64K * 1K = 64MB. This also means that you may use unsigned 16 bit integers in the FAT, making its size a maximum of 64K * 2 = 128KB. However, your FAT should only be as long as it needs to be—if your disk holds 16 MB, the FAT should have 16K entries and thus occupy 32KB of disk space.
Each entry in the FAT contains either the block number of the next block in the file or a "special purpose" number to indicate one of two things: the block is empty, or the block is the last one in the file. Since you'll likely use block 0 for the super block and store the FAT itself starting at block 1, you can use the numbers 0 and 1 for these special purpose numbers.
The FAT should be in a well-known location in the file system; read its location from the superblock.
You can keep the FAT in memory if you want; just make sure you write changes back to disk.
You must support a single directory that can accommodate file names of up to 32 characters. You may not waste space a 4 character file name shouldn't occupy 32 characters of space in the directory. For each file in the directory, you should store the file name, file length (in bytes), and the first block number in the file. This information can be used to read and write the individual blocks of a file. Of course, the directory itself is like a file, and uses the FAT the same way as every other file. The first block in the directory should be readily accessible; as described above, you should store its location in the superblock in other words, the file system should automatically translate "/" into the block number of the directory's first block.
The root directory, as in Unix, is referred to as "/". This means that the call to open the file foo in DLXOS is FsOpen("dlx:/foo", ...). Similar naming applies to the delete call.
There are three possible flags to open: read, write, and create. The read and write flags are used to indicate which operations are permitted on an open file. The create flag is set by the caller when the user wants to create a file if it's not already found. If create isn't set and the file isn't found, an error should be returned. If create is set and the file doesn't yet exist, it should be created with 0 size. Much of the open code is already written for you.
Reading files is self-explanatory. Your file system simply needs to find the appropriate data and read it in. Writing is a bit more complex you may need to allocate a new block. Otherwise, data is written as you'd expect.
File reads and writes need not be on file block boundaries.
Seeks in the DLXOS file system work just the way seeks work in Unix. A seek updates the "current" pointer but doesn't transfer data. Seeks past of the end of the file fail and return a (negative) error code.
Your file system should catch errors and return appropriate error codes. Possible errors you may want to catch include:
You need to write a DLX user program to list all of the files in the (single) directory. You need not list file sizes, though you're certainly allowed to. Keep in mind that listing file sizes will likely require an additional call similar to the Unix stat() system call....
As with other projects, you'll need to hand in your design documentation and your code. Because your code may include both operating system code, user programs, and Unix programs, please make sure your Makefile builds them separately. For this project, you'll need to be particularly careful because you might have programs that need to be compiled with regular (not DLX) gcc. Do not hand in dlxdisk!
For extra credit, you may implement the following features. As usual, the required portion of your code should be substantially working before you attempt extra credit. Please include a list of the extra credit features you've implemented in your README file so we can test them.