The page examines the key concepts and underlying structure of Starnix's virtual file system (VFS):
- Motivation for Starnix's own virtual file system
- Building blocks of the Starnix VFS
- Mounted file systems in the Starnix VFS
Motivation for Starnix's own virtual file system
Starnix has its own virtual file system (which is separate from Fuchsia's VFS) for the reasons below:
Performance – The Starnix VFS allows many file system operations to avoid making FIDL calls. The Starnix VFS does this by caching the results from previous FIDL calls and implementing the entire file system in a process (similar to
tmpfsandprocfs).Compatibility – A file system for Starnix must support several Linux file system operations that are not supported by Fuchsia's VFS libraries, which many Linux-based operating systems rely on. In particular, the following two operations are hard to retrofit into Fuchsia's existing VFS design:
Mounting directories – A Linux file system allows a directory of one file system to be mounted to a directory of another file system.
Tracking a file's path after
open()– A Linux file system can use a file descriptor to determine the path of the file that is opened by anopen()call. If the file or one of its parent directories gets moved or renamed, the file's path must account for this change.
Building blocks of the Starnix VFS
This section constructs a simple file system using the fundamental building blocks of the Starnix VFS:
Files and directories
At the core of the Starnix VFS is a collection of FsNode instances. Each FsNode
contains information about a file or a directory (see Figure 1). File system
operations, such as reading, writing, and retrieving file information, are
performed on FsNode instances.

Figure 1. A simple file system with a directory and a file.
A DirEntry assigns a name to an FsNode. This mapping of DirEntry to FsNode
is referred to as a hard link. Multiple DirEntry instances can be mapped to a
single file-typed FsNode (see Figure 2). This allows multiple paths in a file system
to be resolved to the same FsNode. As a result, multiple paths can be resolved to the
same file content and attributes in a file system. However, while a file can have
multiple hard links, a directory (that is, a directory-typed FsNode) can only have
one hard link.

Figure 2. Multiple DirEntry instances can be mapped to the same FsNode.
A file system
A file system tracks information on a group of related files and directories. In
the Starnix VFS, a file system (that is, a single instance of FileSystem)
represents a collection of DirEntry instances, and each FileSystem instance
contains the following items:
- A
DirEntrypointing to the root directory - A cache of
FsNodeinstances (representing files and directories under the root directory)

Figure 3. A FileSystem tracks DirEntry and FsNode instances.
Mounted file systems in the Starnix VFS
Mounting allows users to seamlessly move from one file system to another file
system. A file system and its contents become available to users (or tasks) once
the file system is mounted to a certain directory. This "mount point" directory
is often a directory of another file system that the users already have access to.
For example, in Figure 4, users can reach the file1.txt file in the Example FS
(file system) by using the path /example/file1.txt from the Parent FS.

Figure 4. The root directory of the Example FS is mounted to the example
directory of the Parent FS.
Mounting a file system and tracking mount points in the Starnix VFS involve the following instances:
Mount
A Mount makes a FileSystem accessible at the mount point directory of
another FileSystem. To put it differently, a Mount is used to link the
following two directories:
- A mount point directory in the parent
FileSystem - The root directory of the child
FileSystem
In Figure 4, the Parent FS has the example directory as a subdirectory and the
Example FS is mounted on this example directory (which is the mount point
directory). In this setup, when you change your working directory to the
example directory in the Parent FS (for instance, cd example is run), you
"enter the mount," that is, you are now in the root directory of the Example FS.

Figure 5. A Mount tracks the root directory of a mounted FileSystem.
To enable the feature of seamlessly moving from the parent FileSystem into the
child FileSystem and vice versa, a Mount tracks a DirEntry that points to the
root directory of the mounted FileSystem (see Figure 5). And a Mount also tracks
its parent Mount using the mountpoint pointer (see
NamespaceNode) and its child Mount instances using the
submounts pointer. (see Figure 6).

Figure 6. Mount's mountpoint and submounts pointers are used to move
between mounted file systems.
It's important to note that a FileSystem can be mounted to a number of different
FileSystem instances at once. This allows the same FileSystem to be reached from
multiple parent FileSystem instances, enabling various paths (or
symlinks) to be used to reach the same file in the mounted
FileSystem.
NamespaceNode
Every task in Starnix contains an instance of FsContext. An FsContext holds
information about the task's association with the Starnix VFS, except for the
file descriptor table.
Importantly, an FsContext contains a Namespace, which
enables the task to identify all FileSystem instances that are mounted under
this namespace. This is possible because each Namespace contains a Mount that
tracks the "root mount" in the namespace (see Figure 7). Using the root mount's
submounts pointer (which points to a map of all DirEntry instances and their
respective Mount instances in the namespace), the task can reach all of the
other mounted FileSystem instances under this namespace.

Figure 7. An FsContext has a Namespace, which has a Mount for tracking the
root mount.
A NamespaceNode is useful for traversing paths in a Namespace. Each
NamespaceNode tracks a Mount and its respective DirEntry.
However, because the same FileSystem can be mounted multiple times in a
Namespace (for instance, at different mount point directories in the same parent
FileSystem), multiple NamespaceNode instances may be necessary to track these
different Mount instances that lead to the same underlying FileSystem.

Figure 8. A FsContext has two NamespaceNode instances for tracking specific
directories: root and cwd.
For instance, each FsContext contains, at a minimum, two NamespaceNode
instances for tracking the following directories (see Figure 8):
- The root directory
- The current working directory (cwd)
Both NamespaceNode instances are used for looking up paths in this Namespace. A
path starting with / (for example, /example/file1.txt) is looked up respective
to the root NamespaceNode, and a path without a starting / (for example,
file1.txt) is looked up using the cwd NamespaceNode.

Figure 9. A simple namespace with a single (root) Mount.
The diagram in Figure 9 illustrates a namespace with a single Mount where the
current working directory (cwd) also happens to be the root directory. The diagram
in Figure 10 shows that the current working directory is changed to the example
directory (for instance, cd example is run), which causes the entry pointer of
the cwd NamespaceNode to be updated to the example directory.

Figure 10. The current working directory is changed to the example directory
in the namespace.
The diagram in Figure 11 shows a namespace where the Example FS is mounted to the
Parent FS. Under this scenario, when cd example is run, the mount pointer of
the cwd NamespaceNode is updated to a new Mount (labeled "Example Mount") that
tracks the root directory of the Example FS. Using this new Mount, the task in
the FsContext can seamlessly move from the Parent FS to the Example FS when
traversing paths.

Figure 11. A namespace where the Example FS is mounted to the example directory of
the Parent FS.
Symbolic links
Symbolic links (or symlinks) are handled while walking NamespaceNode instances.
If the task hits a symlink and asks for its path, the path of this symlink is
resolved recursively from the NamespaceNode.