Operating Systems Practicum

Assignment 3, 2003

File System Compaction

Introduction

After deletion of old files and generation of new files, the blocks of many files in a filesystem will often be noncontiguous, that is, the blocks will no longer be adjacent to each other. In Minix, filesystem fragmentation can occur easily because of its mechanism for allocating new blocks.

Fragmentation can cause performance problems, since reading in a (set of) block(s) of a file means that the disk head has to move to different, possibly non adjacent, locations on the disk. In this project, you have to write a simple defragmentation program.

Program description

The command you need to implement is:

defrag   <oldfs>   <newfs>

Oldfs is the filesystem that needs to be defragmented. Newfs is the device that the defragmented filesystem has to be written to. Newfs may have a different size than oldfs, as long as oldfs fits on the newfs. The new fs should contain a clean minix V2 filesystem, generated using mkfs (see mkfs (1)). Defrag should exit with an error if the old filesystem does not fit on the new filesystem or when the new filesystem is not a V2 filesystem. In that case, newfs is not written. Files or directories that use triple indirect blocks are not supported.

Output

On successful execution, defrag puts one line on standard output, which has the format:
Defragmented filesystem written to /dev/hd3a
where /dev/hd3a should be replaced by the actual output device that the program wrote the output fs to. In case of an error, at most one line of output on standard output is permitted which describes the error that occurred in user-understandable text. Do not place a newline character before your output message. Messages should be written to stdout, not stderr.

Error codes

For any error, return a value > 0. Successful execution results in a 0 being returned. Below is a list of return values that your program should return in case of an error.

Requirements

Additional Hints

Testing

You should generate an fragmented filesystem yourself. An example way to do that is to copy (using cp or dd) the minix root-fs to an empty fs of equal size, and to make some changes to it to make sure that it contains inconsistent files (if it does not contain them already). Use sync prior to copying, and possibly run 'fsck -a' on the copied filesystem afterward to make sure that it does not contain inconsistencies. Do not use defrag on used (mounted) filesystems directly.

You should test all requirements that are listed in this description carefully. fsck (-s) is a useful tool to inspect your output-fs. Of course, you can also mount the target-fs to see whether it still functions and looks the same as the original fs. You should probably use debugging code in your program to see what goes on while defragmenting (e.g., display the input and output inode and zone bitmaps), but make sure that this code is turned off in your submitted assignment (your code may not be accepted for basic testing if it outputs debugging information).

There exist some test partitions on the minix machines in S4.11 at the VU. They are:

        /dev/hd3a       1440k
/dev/hd3b 1440k
/dev/hd3c 70M
/dev/hd3d 70M
You can verify whether the partitions exist using the command:
        df /dev/hd3?

de, the minix disk editor (see de(9)) can be a very convenient tool to inspect the content of your input / output disk. Type ? after starting de to see a list of options.

Hints for implementation

Recommended reading

Most important reading for this assignment is section 5.6 (at least up to 5.6.6). For understanding of the filesystem code, read on in section 5.7. However, as you will not use or change the filesystem code directly, you may skip this section.

For inspiration on how to do things, you may look in /usr/src/fs, and maybe some code in /usr/src/commands/simple/. Inspecting the header files that are included in our example header file defrag.h, and keeping a printout of the header-files containing the relevant data structures beside you can be very handy.

We advise you to write your program completely from scratch. It is forbidden (and also inadviseable) to copy code directly. Most existing code will not do exactly what you want. Furthermore, obvious reuse of existing code will be noticed by us since we know where to look.


Ruediger Weis, ruedi@cs.vu.nl and Guido van 't Noordende
last update: 09.05.2003.