File System Modules

To support a particular file system (FS), a kernel module implementing a special interface (file_system_module_info defined in <fs_interface.h>) has to be provided. As for any other module the std_ops() hook is invoked with B_MODULE_INIT directly after the FS module has been loaded by the kernel, and with B_MODULE_UNINIT before it is unloaded, thus providing a simple mechanism for one-time module initializations. The same module is used for accessing any volume of that FS type.

File System Objects

There are several types of objects a FS module has to deal with directly or indirectly:

Generic Concepts

A FS module has to (or can) provide quite a lot of hook functions. There are a few concepts that apply to several groups of them:

VNodes

A vnode is the VFS representation of a node. As soon as an access to a node is requested, the VFS creates a corresponding vnode. The requesting entity gets a reference to the vnode for the time it works with the vnode and releases the reference when done. When the last reference to a vnode has been surrendered, the vnode is unused and the VFS can decide to destroy it (usually it is cached for a while longer).

When the VFS creates a vnode, it invokes the volume's get_vnode() hook to let it create the respective node handle (unless the FS requests the creation of the vnode explicitely by calling publish_vnode()). That's the only hook that specifies a node by ID; all other node-related hooks are defined in the respective node's operation vector and they are passed the respective fs_vnode object. When the VFS deletes the vnode, it invokes the nodes's put_vnode() hook or, if the node was marked removed, remove_vnode() .

There are only four FS hooks through which the VFS gains knowledge of the existence of a node. The first one is the mount() hook. It is supposed to call publish_vnode() for the root node of the volume and return its ID. The second one is the lookup() hook. Given a fs_vnode object of a directory and an entry name, it is supposed to call get_vnode() for the node the entry refers to and return the node ID. The remaining two hooks, read_dir() and read_query() , both return entries in a struct dirent structure, which also contains the ID of the node the entry refers to.

Mandatory Hooks

Which hooks a FS module should provide mainly depends on what functionality it features. E.g. a FS without support for attribute, indices, and/or queries can omit the respective hooks (i.e. set them to NULL in the module, fs_volume_ops, and fs_vnode_ops structure). Some hooks are mandatory, though. A minimal read-only FS module must implement:

Although not strictly mandatory, a FS should additionally implement the following hooks:

Checking Access Permission

While there is the access() hook that explicitly checks access permission for a node, it is not used by the VFS to check access permissions for the other hooks. This has two reasons: It could be cheaper for the FS to do that in the respective hook (at least it's not more expensive), and the FS can make sure that there are no race conditions between the check and the start of the operation for the hook. The downside is that in most hooks the FS has to check those permissions. It is possible to simplify things a bit, though:

Node Monitoring

One of the nice features of Haiku's API is an easy way to monitor directories or nodes for changes. That is one can register for watching a given node for certain modification events and will get a notification message whenever one of those events occurs. While other parts of the operating system do the actual notification message delivery, it is the responsibility of each file system to announce changes. It has to use the following functions to do that:

If the file system supports queries, it needs to call the following functions to make live queries work:

Caches

The Haiku kernel provides three kinds of caches that can be used by a file system implementation to speed up file system operations: