How Linux VFS Mounts ext4: Deep Dive into Superblocks, Inodes, and Dentries
This article explains the object‑oriented design of the Linux VFS, details the four core VFS structures, shows how ext4 is registered and mounted via register_filesystem and ext4_mount, and walks through the six‑step ext4_fill_super process for initializing superblocks and related metadata.
Mounting to Linux VFS
VFS Objects
VFS follows an object‑oriented design, abstracting key concepts into C structures that contain both data and the operations on that data. The four primary VFS objects are:
Superblock (struct super_block) : Represents a mounted filesystem and stores information such as type, size, and status. For disk‑based filesystems it resides on a specific disk sector; for memory‑based filesystems (e.g., sysfs) it is created in memory.
Inode (struct inode) : Represents a physical file on a storage device and holds metadata like permissions, size, and timestamps.
Dentry (struct dentry) : Describes a component of the filesystem hierarchy. Every path component—whether a directory (treated as a file) or a regular file—has a dentry object.
File (struct file) : Represents an opened file instance for a process, created by
open()and destroyed by
close(). Multiple file objects can refer to the same inode.
Additional VFS structures include
struct file_system_type(describing filesystem types) and
struct vfsmount(describing mount points).
Filesystem Mounting
Before the kernel can use a filesystem type, it must be registered. For ext4 this is done with
register_filesystem(&ext4_fs_type), where the most important member is
ext4_mount.
<code>register_filesystem(&ext4_fs_type);
static struct file_system_type ext4_fs_type = {
.owner = THIS_MODULE,
.name = "ext4",
.mount = ext4_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};</code>The actual mount operation is performed by
ext4_mount, which delegates to
mount_bdevto handle block devices.
<code>static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
}
struct dentry *mount_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int))
{
struct block_device *bdev;
struct super_block *s;
fmode_t mode = FMODE_READ | FMODE_EXCL;
int error = 0;
if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;
/* get the device */
bdev = blkdev_get_by_path(dev_name, mode, fs_type);
if (IS_ERR(bdev))
return ERR_CAST(bdev);
/* ... omitted error handling and superblock initialization ... */
return dget(s->s_root);
error_s:
error = PTR_ERR(s);
error_bdev:
blkdev_put(bdev, mode);
error:
return ERR_PTR(error);
}
</code>After
mount_bdevreturns,
ext4_fill_superreads the on‑disk
ext4_super_block, creates and initializes an
ext4_sb_infostructure, and links it to the generic
super_block.
The
ext4_sb_infodefinition and the core of
ext4_fill_superare shown below.
<code>struct ext4_sb_info {
struct buffer_head *s_sbh; /* Buffer containing the super block */
struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */
struct buffer_head **s_group_desc;
};
static int ext4_fill_super(struct super_block *sb, void *data, int silent)
{
struct ext4_sb_info *sbi;
struct buffer_head *bh;
struct ext4_super_block *es = NULL;
/* ... read super block, set up sbi fields, calculate groups, allocate descriptors ... */
return 0;
}
</code> ext4_fill_superproceeds in six steps:
Read the
ext4_super_block(initially assuming a 1024‑byte block size).
Re‑calculate the logical superblock location and offset based on the actual block size (e.g., 4096 bytes).
Assign the retrieved super block to the
ext4_sb_infofields.
Validate all group descriptor data and initialise flex‑bg information.
Obtain the filesystem root inode with
ext4_igetand create the root dentry.
Call
ext4_setup_superfor final checks, write back changes, and update mount counters.
Each mounted filesystem has a unique
struct file_system_type(e.g.,
ext4_fs_type) and one or more
struct vfsmountinstances representing mount points. The diagram below shows the relationship between superblocks, mount points, and specific filesystem instances.
Recovering Deleted Files Is Not Mysterious
On most disk‑based filesystems, data consists of metadata (information about files and directories) and the file contents themselves. Deleting a file typically removes only the metadata, leaving the actual content untouched until it is overwritten. This makes recovery possible if the blocks have not been reused, but also poses a security risk.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.