簡單記錄一下Linux 4.19-rc8從mount system call到呼叫file_system_type.mount()的call flow
SYSCALL_DEFINE5(mount)
|--> ksys_mount()
|--> do_mount()
|--> do_new_mount()
|--> type = get_fs_type()
|--> vfs_kern_mount(type)
|--> mount_fs(type)
|--> type->mount()
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
return ksys_mount(dev_name, dir_name, type, flags, data);
}
int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type,
unsigned long flags, void __user *data)
{
int ret;
char *kernel_type;
char *kernel_dev;
void *options;
kernel_type = copy_mount_string(type);
...
kernel_dev = copy_mount_string(dev_name);
...
options = copy_mount_options(data);
...
ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
...
return ret;
}
long do_mount(const char *dev_name, const char __user *dir_name,
const char *type_page, unsigned long flags, void *data_page)
{
struct path path;
unsigned int mnt_flags = 0, sb_flags;
int retval = 0;
retval = user_path(dir_name, &path);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags, sb_flags, mnt_flags, data_page);
else if (flags & MS_BIND)
retval = do_loopback(&path, dev_name, flags & MS_REC);
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
retval = do_change_type(&path, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&path, dev_name);
else
retval = do_new_mount(&path, type_page, sb_flags, mnt_flags, dev_name, data_page);
...
return retval;
}
static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
int mnt_flags, const char *name, void *data)
{
struct file_system_type *type;
struct vfsmount *mnt;
int err;
type = get_fs_type(fstype);
...
mnt = vfs_kern_mount(type, sb_flags, name, data);
...
put_filesystem(type);
...
err = do_add_mount(real_mount(mnt), path, mnt_flags);
...
return err;
}
struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct mount *mnt;
mnt = alloc_vfsmnt(name);
...
root = mount_fs(type, flags, name, data);
...
return &mnt->mnt;
}
struct dentry *
mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
struct dentry *root;
...
root = type->mount(type, flags, name, data)
...
return root;
}
參考資料:
- https://lkml.org/lkml/2018/3/16/905, fs: add ksys_mount() helper; remove in-kernel calls to sys_mount()
- https://www.halolinux.us/kernel-architecture/the-mount-system-call.html, The Mount System Call