As mentioned in the introduction, some file systems are implemented as in-kernel modules that export the vnode interface. They typically implement ``meta'' operations on files or groups of files, relying on other device level file systems for file access. Examples include Solaris' Cachefs [SunSoft94], and the Online Disk-Suite (OLDS) of file systems (offering mirroring, striping, and device concatenation) [SMCC93b].
For example, the mirroring file system of the Online Disk-Suite is a module that stacks on top of two or more physical file systems. Each vnode operation in the mirroring file system performs ``meta'' operations on the native file systems it stacked on top of. For example, the read call reads data from either one of the replicas and returns the first one that replies; the write call writes data to all replicas and will not return a success status until the data have been successfully written to all copies.
To access a particular file system, processes make system calls that get translated into vnode interface calls, as depicted in Figure fig-level-vnode.
Vnode level file systems exhibit the same advantages and disadvantages as device level file systems, though to a lesser degree. Kernel residence makes writing such file systems difficult, but their performance is good.
The FiST compiler produces code for either a vnode level file system or one running at user level. The first reason for choosing the vnode level over device and user levels is that most proposals for new file systems are proposals for ``meta'' semantics rather than new ways to organize bits on devices. The second reason is the possibility of good performance because a kernel-resident implementation avoids costly context switches, and runs in a higher privileged mode than user level. The third reason is the potential for portable code because most brands of Unix implement some version of the vnode interface.
Debugging kernel resident file systems is still difficult. For that reason, I decided that FiST will also generate file system modules to run in user level, where they can be inspected with greater ease using standard debuggers. These modules will be generated to an API that is supported by Amd (NFS). Amd will be able to dynamically load these file systems and provide new semantics based on the FiST descriptions thereof.
Supporting both user and kernel level file systems from the same FiST description provides the best of both worlds: you get (a) good performance when running in the kernel, and (b) easier development when running modules in Amd.