如果一种文件系统的类型曾经在内核注册过,这就说明允许挂载并且使用这个文件系统。
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, };
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { ...... ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options); ...... } //接下来的调用链为:do_mount->do_new_mount->vfs_kern_mount struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { ...... mnt = alloc_vfsmnt(name); ...... root = mount_fs(type, flags, name, data); ...... mnt->mnt.mnt_root = root; mnt->mnt.mnt_sb = root->d_sb; mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts); return &mnt->mnt; }
vfs_kern_mount 先是创建 struct mount 结构,每个挂载的文件系统都对应于这样一个结构。
struct mount { struct hlist_node mnt_hash; struct mount *mnt_parent; // 装载点所在的父文件系统 struct dentry *mnt_mountpoint; // 装载点在父文件系统中的dentry struct vfsmount mnt; union { struct rcu_head mnt_rcu; struct llist_node mnt_llist; }; struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ struct list_head mnt_instance; /* mount instance on sb->s_mounts */ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; ...... } __randomize_layout; struct vfsmount { // 当前文件系统根目录的dentry struct dentry *mnt_root; /* root of the mounted tree */ struct super_block *mnt_sb; /* pointer to superblock */ int mnt_flags; } __randomize_layout;
调用 mount_fs 挂载文件系统。
struct dentry * mount_fs(struct file_system_type *type, int flags, const char *name, void *data) { struct dentry *root; struct super_block *sb; ...... root = type->mount(type, flags, name, data); //比如ext4_mount ...... sb = root->d_sb; ...... }