On-Disk data structures

Numeric format

All numbers in the CleanFS filesystem are stored on-disk in Little-Endian format. Unless a number is specifically defined as unsigned, all numbers are signed, and if negative numbers don't have a meaning, then they become reserved for future use and the implementation should not use the negative number range. 

Boot Record

The CleanFS file system is intended for embedded systems, and therefore there is no requirement to have a boot sector to boot an operating system, like there is on a PC. There is, however, the need to store sensitive information about the file system, like sectors per cluster, total number of clusters, etc.

The CleanFS filesystem stores that information on the first sector of the volume. The first sector of a volume can also be "shared" with the root directory, and in that case the boot record becomes the first entry in the root directory (however, it should not be visible as a file).

Since this will be the most common case, the boot record actual on-disk format will be discussed as an entry record of a directory. Stand-alone boot records must have the same structure.

Files

Files are stored as a group of clusters on the disk, which may or may not be contiguous. Files are written to these clusters as raw data, no metadata of any kind will be stored with the files.

Directories

The directories are the most important feature of the CleanFS file system. A directory is a file, which contains all the information necessary to access other files, that are said to be "within" the directory.

Directories are stored as raw data, same as a any other file, and consist of a group of clusters (contiguous or not).

The CleanFS file system follows these guidelines when it comes to directories:

  • Directories must store ALL information about a file: There is no inodes, FAT table, MFT table, or any other table in the file system. This is unlike FAT and unlike most Unix file systems. This is a consequence of the basic idea to minimize I/O. Once the directory is read, everything needed to access a file is known, therefore no more disk access is needed other than to read the actual data on the file. Modern file systems include journals, and tables that need to be updated. For example, to create a file on an EXT file system, the directory entry needs to be created, which stores the file name (that's one disk write at the directory), then the inode must be created and written, with the rest of the file information (that's another write), then a journal entry must be written, on top of writing the actual file data. FAT is simpler because there's no journal, but the system must write the directory, the FAT table and then the file. CleanFS only writes the directory and the file data, making it even simpler, and in systems where I/O bandwidth is limited, less I/O means faster operation.
  • Directories must be self-contained: A directory must contain all information needed to access itself. In order to do that, the first cluster of a directory must contain an entry named '.' (from the '.' and '..' entries, which historically refers to itself and the parent dir respectively). This entry contains the information that defines which clusters is the directory stored in, and allows to access everything.

The on-disk format of a directory is a sequence (list) of fixed-length records. Each record is 64 bytes long, and all numbers must be stored in Little Endian format (LSB goes first). An entry in the directory can use one or more consecutive records.

The first 32-bits of the record indicate the record type, then there's 60 bytes of "payload" that depend on the record type. There are two kinds of records:

  • Primary records: Define the beginning of an entry (an entry could be a file, the boot record or any other type of entity)
  • Secondary records: Provide additional data about the entry with the preceding primary record

In other words, an entry will begin with a primary record, that may or may not be followed by secondary records. The end of an entry is defined by either the end of the directory or the presence of another primary record.

The next section will reveal the internals of each record type.