How Does a Virtual File System Mount Diverse Storage Formats?

The Virtual File System is an abstraction layer inside an operating system kernel that provides a uniform interface for applications and system calls to interact with different file systems. By separating the generic file operations from the specific details of how data is organized on disk or over a network, it allows the operating system to mount and use diverse storage formats seamlessly.

The Role of the Virtual File System

In classical computing, storage devices and file systems vary widely in how they structure data, manage metadata, and handle permissions. A local solid-state drive might use ext4 or NTFS, a USB flash drive might use FAT32 or exFAT, and a remote server might expose files over NFS or SMB. Without an abstraction layer, every application or system utility would need custom logic to read and write to each format.

The Virtual File System (VFS) solves this by acting as a translation boundary. User-space programs issue standard system calls such as open(), read(), write(), and close(). The VFS intercepts these calls and routes them to the appropriate underlying file system driver, which translates the generic request into format-specific operations.

Core VFS Data Structures

To present a unified view of all mounted storage, the VFS relies on a small set of standardized kernel objects:

  • Superblock: Represents a mounted file system as a whole. It stores metadata about the file system type, block size, total capacity, and pointers to operations that affect the entire volume.
  • Inode (Index Node): Represents an individual file or directory. It holds metadata such as file size, ownership, timestamps, and permissions, along with a pointer to the file's data blocks.
  • Dentry (Directory Entry): Represents a specific path component and links a human-readable name to an inode. Dentries are cached in memory to speed up path resolution.
  • File Object: Represents an open file associated with a running process. It tracks the current read/write offset, access mode, and the operations table for that file.

Function Pointer Tables and Dispatch

The key mechanism that enables seamless polymorphism in the VFS is the use of function pointer tables (often implemented as C structs containing function pointers). Each VFS object contains an operations structure, such as inode_operations or file_operations.

When a file system driver registers with the kernel, it provides its own implementations for these operations. For example:

  1. An ext4 driver populates the file_operations table with ext4_file_read_iter and ext4_file_write_iter.
  2. A FAT32 driver populates the same table with fat_file_read and fat_file_write.
  3. A network file system like NFS populates it with functions that serialize requests into network packets.

When an application calls read(), the VFS looks up the file object for that file descriptor and invokes file->f_op->read(). The kernel executes the exact driver function needed for that storage format without the caller knowing or caring which format is underneath.

Mounting Diverse Formats into a Single Tree

In Unix-like operating systems, the VFS unifies all mounted file systems into a single hierarchical directory tree starting at /. When a storage device is mounted at a directory (the mount point), the VFS attaches the new file system's root dentry and superblock to that location in the tree.

When a process traverses a path such as /mnt/usb/notes.txt, the VFS walks the dentry cache component by component. Upon reaching /mnt/usb, it detects that a mount point is present, switches context to the mounted file system's superblock, and continues resolving notes.txt using the USB drive's driver. This allows a single path lookup to cross seamlessly from an ext4 root partition onto a FAT32 drive or a virtual pseudo-file system like /proc.

Benefits of the VFS Abstraction

  • Application Portability: Programs use the same POSIX or OS-native APIs regardless of whether data resides on local flash storage, optical media, or a remote server.
  • Modular Driver Architecture: New file systems can be developed and loaded as kernel modules without modifying existing applications or core kernel syscalls.
  • Shared Caching: Because the VFS sits above individual drivers, the kernel can maintain a unified page cache and dentry cache, improving performance across all mounted formats.