Linux Virtual Filesystem
Contents
Virtual Filesystem Intro
VFS Design: VFS is designed to be flexible and modular, allowing new file systems to be added easily. As new storage and network technologies are developed, VFS ensures that the operating system can interact with them. Through a common API, VFS provides consistent system calls for file operations such as open, read, write, and close, no matter the file system type.
VFS enables the “everything is a file” abstraction in Unix-like systems.

Filesystem Interface
The VFS is the glue that enables system calls such as
open(),read(), andwrite()to work regardless of the filesystem or underlying physical medium. Such a generic interface is feasible only because the kernel implements an (Filesystem) abstraction layer around its low-level filesystem interface.
Example: ret = write (fd, buf, len);
On one side of the system call is the generic VFS interface, providing the frontend to user-space; on the other side of the system call is the filesystem-specific backend, dealing with the implementation details.

Unix Filesystems Concepts
In Unix, filesystems are mounted at a specific mount point in a global hierarchy known as a
namespace. This enables all mounted filesystems to appear as entries in a single tree. Different filesystems (which could even be on different devices or remote locations) are attached to specific directories in the Unix file hierarchy.
VFS Objects and Data Structures
The four primary object types of theVFS are:
- The
superblockobject, which represents a specific mounted filesystem. - The
inodeobject, which represents a specific file. - The
dentryobject, which represents a directory entry, which is a single component of a path. - The
fileobject, which represents an open file associated with a process.
operations object is contained within each of these primary objects.These objects describe the methods that the kernel invokes against the primary objects.
The operations objects are implemented as a structure of pointers to functions that operate on the parent object.
- The
super_operationsobject contains methods that the kernel can invoke on a specific filesystem, such aswrite_inode()andsync_fs(). - The
inode_operationsobject contains methods that the kernel can invoke on a specific file, such ascreate()andlink(). - The
dentry_operationsobject contains methods that the kernel can invoke on a specific directory entry, such asd_compare()andd_delete(). - The
file_operationsobject contains methods that a process can invoke on an open file, such asread()andwrite().
VFS loves structures. It has more than the primary objects mentioned before. Each registered filesystem is represented by file_system_type structure, describing the filesystem and its capabilities. Each mount point is represented by vfsmount structure, containing information such as location and mount flags.
The Superblock Object
struct super_blockdefined in<linux/fs.h>
Superblock Operation
Due to the lack of object-oriented support in C, there is no way for the method to easily obtain its parent, so you have to pass it. An example of a same code between C and C++:
sb->s_op->write_super(sb); // C
sb.write_super(); // C++
The Inode Object
struct inodeand is defined in<linux/fs.h>
Inode Operation
inode_operationsdefined in<linux/fs.h>
The Dentry Object
Context: VFS treats directories as a type of file. In the path
/bin/vi, bothbinandviare files -binbeing the special directory file andvibeing a regular file. Despite this useful unification, VFS often needs to perform directory-specific operations, such as path name lookup. Path name lookup involves translating each component of a path, ensuring it is valid, and following it to the next component.
struct dentrydefined in<linux/dcache.h>
- Unlike the previous two objects, the dentry object does not correspond to any sort of on-disk data structure. Dentry object is not physically stored on the disk.
- TheVFS creates it on-the-fly from a string representation of a path name.
Dentry State
-
used: A used dentry corresponds to a valid inode (d_inodepoints to an associated inode) and indicates that there are one or more users of the object (d_countis positive). A used dentry is in use by the VFS and points to valid data, and thus cannot be discarded. -
unused: An unused dentry refers to a valid inode(d_inodepointing to an inode), but the VFS is not currently using the dentry object (d_countis zero). Dentry object is kept around as a cache in case it is needed again.By caching the dentry instead of destroying it early, the dentry won’t need re-creation if it’s needed in the future. This speeds up path name lookups. If memory needs to be reclaimed, the dentry can be discarded because it’s not in use.
-
negative: not associated with a valid inode (d_inodeis NULL) because either the inode was deleted or the path name was never correct to begin with. The dentry is kept around, however, so that future lookups are resolved quickly.Consider a daemon that tries to read a missing config file, causing costly failed lookups. Caching these negative results can be worthwhile.
Dentry Cache
The dentry cache consists of three parts:
- Lists of “used” dentries linked off their associated inode via the i_dentry field of the inode object.
- A doubly linked “least recently used” list of unused and negative dentry objects.
The list is inserted at the head, such that entries toward the head of the list are newer than entries toward the tail. When the kernel must remove entries to reclaim memory, the entries are removed from tail; those are the oldest and presumably have the least chance of being used in the near future.
- A hash table and hashing function used to quickly resolve a given path into the associated dentry object.
Hash table is represented by the dentry_hashtable array. Each element is a pointer to a list of dentries that hash to the same value.
Example: Assume that you are editing a source file in your home directory, /home/dracula/src/the_sun_sucks.c. Each time this file is accessed (for example, when you first open it), the VFS must follow each directory entry to resolve the full path:/,home,dracula,src,and finally the_sun_sucks.c.To avoid this time-consuming operation each time this path name is accessed, the VFS can first try to look up the path name in the dentry cache. If the lookup succeeds, the required final dentry object is obtained without serious effort. Conversely, the VFS must manually resolve the path by walking the filesystem for each component of the path. After this task is completed,the kernel adds the dentry objects to the dcache to speed up any future lookups.
Dentry Operation
dentry_operationsstructure is defined in<linux/dcache.h>
The File Object
The file object is the in-memory representation of an open file.The object (but not the physical file) is created in response to the
open()system call and destroyed in response to theclose()system call. Because multiple processes can open and manipulate a file at the same time, there can be multiple file objects in existence for the same file.
struct fileand is defined in<linux/fs.h>
File Operations


Some Important Operations:





Data Structures Associated with Filesystems
file_system_type
file_system_typeis defined in<linux/fs.h>
get_sb()function reads the superblock from the disk and populates the superblock object when the filesystem is loaded.
vfsmount
vfsmountstructure is defined in<linux/mount.h>
-
It’s complicated to maintain the relation between the filesystem and all the other mount points. The various linked lists in
vfsmountkeep track of this information. -
mnt_flagsspecifies the standard mount flagsThese flags are useful on removable devices that the admin does not trust.

Data Structures Associated with a Process
-
files_struct is used by the Linux kernel to keep track of all of the open files for a process.

- The array
fd_arraypoints to the list of open file objects.NR_OPEN_DEFAULTis 64, but you can adjust this macro as needed.
- The array
-
fs_struct contains filesystem information related to a process and is pointed at by the fs field in the process descriptor.

-
namespace enable each process to have a unique view of the mounted filesystems on the system—not just a unique root directory, but an entirely unique filesystem hierarchy.


- The
listmember specifies a doubly linked list of the mounted filesystems that make up the namespace.
- The
Conclusion
Linux supports a wide range of file systems, from native file systems such as ext3 and ext4, to networked file systems such as NFS and Coda. There are more than 60 file systems alone in the official kernel.
The VFS layer provides these disparate file systems with both a framework for their implementation and an interface for working with the standard system calls. The VFS layer makes it easy to implement new file systems in Linux and enables those file systems to automatically interoperate via the standard Unix system calls.












