2020年5月9日 星期六

Linux Kernel(18.2)- SysCall mount


簡單記錄一下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




沒有留言:

張貼留言

熱門文章