// vfs层保留该小节需要的核心字段
struct super_block {
// 文件系统类型
struct file_system_type *s_type;
// 文件系统super_block的操作函数
const struct super_operations *s_op;
// 根目录
struct dentry *s_root;
// 每个实际文件系统的超级块,比如ext4,这里就会存储ext4的super block
void *s_fs_info; /* Filesystem private info */
} __randomize_layout;
// 实际的ext4文件系统,super_block中的s_type中存储了ext4_fs_type的信息
static struct file_system_type ext4_fs_type = {
.owner = THIS_MODULE,
.name = "ext4",
// vfs层对应的mout的时间函数
.mount = ext4_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
// ext4作为kernel module形式注入kernel,在ext4_init_fs注册文件系统
static int __init ext4_init_fs(void)
{
register_filesystem(&ext4_fs_type);
}
// 应用端发出mount命令挂载的系统调用
COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
const char __user *, dir_name,
const char __user *, type, compat_ulong_t, flags,
const void __user *, data)
{
// 实际是调用内核的do_mount函数来完成mount操作
retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
}
long do_mount(const char *dev_name, const char __user *dir_name,
const char *type_page, unsigned long flags, void *data_page)
{
do_new_mount(&path, type_page, sb_flags, mnt_flags,
dev_name, data_page);
}
static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
int mnt_flags, const char *name, void *data)
{
// 根据文件系统类型名称获取文件系统的内核module.这里是ext4会根据ext4来获取ext4 文件系统的kernel module
type = get_fs_type(fstype);
// 为此次文件系统挂载创建文件系统挂载上下文
fc = fs_context_for_mount(type, sb_flags);
// 在这里实际调用文件的mount函数赋值,比如这是ext4_mount.
err = vfs_get_tree(fc);
// 内核开始进行挂载
err = do_new_mount_fc(fc, path, mnt_flags);
}
// 初始化一个fs_context,同时给fs_context中的struct dentry *root,这个root包含了dentry和super_block.其中root是通过 legacy_get_tree中调用具体文件系统的mount函数,这里是调用ext4_mount函数,初始化root dentry
struct fs_context *fs_context_for_mount(struct file_system_type *fs_type,
unsigned int sb_flags)
{
return alloc_fs_context(fs_type, NULL, sb_flags, 0,
FS_CONTEXT_FOR_MOUNT);
}
static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
struct dentry *reference,
unsigned int sb_flags,
unsigned int sb_flags_mask,
enum fs_context_purpose purpose)
{
// ext4中ext4_fs_type并没有的函数指针为空
init_fs_context = fc->fs_type->init_fs_context;
if (!init_fs_context)
// 这里默认init_fs_context
init_fs_context = legacy_init_fs_context;
// legacy_init_fs_context调用,fs_context->ops = &legacy_fs_context_ops;这里legacy_fs_context_ops定义了函数指针表。这里谈到的是vfs层的mount系统调用和实际的文件系统的mount有有关的就是legacy_fs_context_ops.get_tree函数
ret = init_fs_context(fc);
}
// 新内核引入的fs_context_operations,vfs层的mount是是如何和真实的文件系统mount函数挂钩,这里就是调用fs_context_operations.get_tree实现
const struct fs_context_operations legacy_fs_context_ops = {
.free = legacy_fs_context_free,
.dup = legacy_fs_context_dup,
.parse_param = legacy_parse_param,
.parse_monolithic = legacy_parse_monolithic,
//这里是调用真是文件系统的ext4_mount函数
.get_tree = legacy_get_tree,
.reconfigure = legacy_reconfigure,
};
// 在这里调用真实文件系统的ext4的mount函数入口
int vfs_get_tree(struct fs_context *fc)
{
// get_tree指向legacy_get_tree函数
error = fc->ops->get_tree(fc);
}
// do_mount函数会调用do_new_mount,而do_new_mount函数会调用do_new_mount_fc来针对每个挂载的文件系统创建struct mount结构,然后再这个函数里面调用do_add_mount完成ext4文件系统的挂载
static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
unsigned int mnt_flags)
{
struct vfsmount *mnt;
struct super_block *sb = fc->root->d_sb;
mnt = vfs_create_mount(fc);
mnt_warn_timestamp_expiry(mountpoint, mnt);
error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
if (error < 0)
mntput(mnt);
return error;
}
// 这里是挂载实际文件系统的mount的函数调用
static int legacy_get_tree(struct fs_context *fc)
{
struct legacy_fs_context *ctx = fc->fs_private;
struct super_block *sb;
struct dentry *root;
root = fc->fs_type->mount(fc->fs_type, fc->sb_flags,
fc->source, ctx->legacy_data);
if (IS_ERR(root))
return PTR_ERR(root);
sb = root->d_sb;
BUG_ON(!sb);
fc->root = root;
return 0;
}