CS 134

Filesystem Layers

When designing systems, it's often the case that the design process becomes more manageable when we break the system down into layers. For filesystems, we can think of the relevant layers as follows:

  1. High-Level Filesystem: This layer understands concepts like filenames, directories, and permissions. It allows files to be of arbitrary length in bytes, and allows reading and writing starting from any offset in a file. This layer is what most users interact with when they use a computer. This functionality is built on top of the low-level filesystem.
  2. Low-Level Filesystem: This layer provides a more rudimentary concept of files. Files are just numeric file IDs, and the filesystem provides a way to read and write logical blocks of data to these files. Sizes of low-level files are typically multiples of the logical block size.
  3. Block Device: This layer provides a way to read and write logical blocks of data to a disk, and is what the low-level filesystem uses to read and write data to the disk. The block device layer may provide buffering of writes and caching of reads to improve performance.

Although we might prefer to have strict and clear boundaries between these layers, in practice, in real operating systems, the layers are often more intertwined. For example, the low-level filesystem might have some knowledge of the block device and store some special information on behalf of the high-level filesystem.

In this lesson, we'll focus on the low-level filesystem, and in the next lesson, we'll build on that to understand the high-level filesystem.

A Low-Level Filesystem Interface

Let's envision a low-level filesystem interface, starting with the following functions:

  • create(): Create a new file and return its file ID.
  • delete(fileID): Delete a file.
  • read(fileID, blockNum, count): Read data from a file starting at a block number and reading a certain number of blocks.
  • write(fileID, blockNum, count, data): Write data to a file starting at a block number and writing a certain number of blocks.

Some aspects of this interface are rather loosely defined. What are some aspects that need more clarity? (e.g., “What happens if you…?” or “How do you…?”)

  • Cat speaking

    Can I write to a block that isn't already part of the file? If not, how do I add blocks to a file?

  • Hedgehog speaking

    How do I know how big a file is?

  • Duck speaking

    Can I make a gap in the middle of a file by not writing to some of the blocks? If so, can I later find out where the gaps are?

  • Pig speaking

    What about putting MORE blocks into a file? And can I put them in the middle of a file?

Let's clarify and extend the interface to address some of these questions:

  • extend(fileID, count): Extend a file by a certain number of blocks.
  • size(fileID): Return the size of a file in blocks.

We'll make some features optional, including

  • Files with gaps in the middle.
  • Inserting blocks into the middle of a file.

By default, we'll assume that our low-level filesystem doesn't support these features as they're not essential, but we'll note when it would technically be possible to add them.

  • Horse speaking

    Hay! Wouldn't it be useful to have a create(size) function to create a file of a particular size?

  • Duck speaking

    But you can always create a(n empty) file and then extend it to the desired size, right?

  • PinkRobot speaking

    Yes, we can make do without create(size), but it would certainly be convenient for the low-level layer to know how big a file is supposed to be from the start. In practice, the higher-level layer doesn't provide any way to specify the size of a file when it's created, so in practice it would always be called as create(0), so we don't bother with it here.

  • Rabbit speaking

    Actually, sometimes the high-level API provides a clonefile or copyfile call that creates a new file of the same size as an existing file, so there are cases where the size of a file is specified at creation time in the high-level API.

  • Goat speaking

    Meh. Whatever. Worse is better and all that.

(When logged in, completion status appears here.)