Why Yet Another File-System

  1. Why not?
  2. To get intimate knowledge with the VFS...
  3. ... so we can contribute to a "real" FS (ext2, reiserfs, nfs...)
  4. Because we think we have an idea for an even better FS.
  5. To expose something that's not an FS, as if it was one (e.g. ftpfs).
  6. To be able to prepare an unusual lecture for our local LUG.
  7. To leverage two month of unemployment for a future career...

General Parts Of A Disk-Based File-System's code

Copy copy, luki luki...

The Disk-Layout Of STAMFS

The Inode Index

The Disk-Layout Of A STAMFS Inode

The Free Blocks List

The Directory Index

Writing STAMFS - A Loop With 8 Iterations

Registering A New File-System

Here is the non-mountable STAMFS code.

Making It Mount-able

To make the file-system mountable, we implement the "stamfs_read_super()" function:

Loading An Inode From Disk

The "iget()" function we called to load the root inode will eventually invoke the read_inode super-block operation, stamfs_read_inode():

And "Cleanly" Un-mount-able

When a file-system is unmounted, its "put_super" super-block operation is invoked. stamfs_put_super() does:

"Cleanly" Release Inodes

When we read the inode, we attached a meta-information structure to the inode object. When the system frees this object, we need to clear this memory. This is done by implementing the 'clear_inode' super-block operation:

Here is the just-mountable STAMFS code.

The Lookup Operation

Now we should allow searching for inodes inside directories, based on their names - a simple "ls" won't work without stamfs_iop_lookup:

Reading The Contents Of A Directory

If we'll just stop here, we'll get a system crash in the first "ls" to the root directory - we want to be able to read the contents of the root directory, and this requires a file-operation named readdir, implemented in stamfs_readdir():

Now, here is the search-able STAMFS code.
Note: expect a kernel-panic when bdflush tries to sync this directory - we'll get back to this later...

Support Directory Creation

When we instantiated the root-inode, we attached an inode-operations object - struct stamfs_dir_iops. It has a "mkdir" entry - to which we now attach stamfs_iop_mkdir():

Creating A New Inode

To create a new inode, we have stamfs_inode_new_ino():

Important - Writing The Super-Block

If we want to avoid a busy-loop, we must implement write-super:

So, here is the mkdir-able STAMFS code.

Support Directory Deletion

After we can create directories - we can try to delete them, too, with stamfs_iop_rmdir():

Support Directory Deletion - The Unlink Operation

Unlink is implemented as a separate operation, since later on it will also be used to unlink files:

Now, here is the rmdir-able STAMFS code.

Making Changes Persistent

Until now, when we unmounted our file-system, we lost all entires we created (well, not all - when we wrote into buffer-heads, they got written into disk - which is why we got some funny entries in directories, after un-mounting and re-mounting a file system on which we created directories).

We need to have the following:

Writing Inodes Back To Disk

Writing inodes back to disk is done using the super-block's write_inode operation, and the stamfs_write_inode() function, which simply invokes stamfs_inode_write_ino():

Deleting Inodes From Disk

Deleting inodes from disk is done using the super-block's delete_inode operation, and the stamfs_delete_inode() function:

Truncating An Inode's Data Blocks

This function is used both when deleting the inode, and when a user invokes a "truncate" operation (with a given offset) on a file, so it uses the inode's size field in order to know where to start truncating from:

Now, here is the persistent STAMFS code.

Creating Normal Files

First, we need to add new operation structs for files: