文件系统mount过程

SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
dev_name:设备名
dir_name:挂载的目录
type:文件系统内型
flags:挂载标志
data:文件系统相关数据,


SYSCALL_DEFINE5(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_dir;
char *kernel_dev;
unsigned long data_page;


ret = copy_mount_string(type, &kernel_type);从用户空间拷贝到内核空间
先计算长度,再kmalloc,然后copy_from_user
kernel_dir = getname(dir_name);从用户空间拷贝到内核空间
从names_cachep里分配一个slab,然后直接__do_strncpy_from_user(汇编拷贝)
ret = copy_mount_string(dev_name, &kernel_dev);


ret = copy_mount_options(data, &data_page);

ret = do_mount(kernel_dev 目标设备, kernel_dir 挂载目录, kernel_type 类型, flags 标志,(void *) data_page 数据);
}
long do_mount(char *dev_name 目标设备, char *dir_name 挂载目录, char *type_page 文件系统类型,
 unsigned long flags 标志, void *data_page 数据)
{
struct path path; 挂载文件系统时的路径结构
int retval = 0;
int mnt_flags = 0;


/* 过滤 魔数 */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
flags &= ~MS_MGC_MSK;


/* 基本完整性检查*/
if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
return -EINVAL;


if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;


/* ... and get the mountpoint */
retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); 
获得挂载点的目录path.dentry和vfsmount结构path.mnt


retval = security_sb_mount(dev_name, &path,
  type_page, flags, data_page);



/* Default to relatime unless overriden */
if (!(flags & MS_NOATIME))
mnt_flags |= MNT_RELATIME;


/* Separate the per-mountpoint flags */
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
if (flags & MS_NODEV)
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
if (flags & MS_NOATIME)
mnt_flags |= MNT_NOATIME;
if (flags & MS_NODIRATIME)
mnt_flags |= MNT_NODIRATIME;
if (flags & MS_STRICTATIME)
mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
if (flags & MS_RDONLY)
mnt_flags |= MNT_READONLY;


flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
  MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
  MS_STRICTATIME);


if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, 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, flags, mnt_flags,
     dev_name, data_page);


}


static int do_new_mount(struct path *path 挂载点的路径结构, char *type 文件系统类型, int flags 挂载标志,
int mnt_flags 内核挂载标志, char *name 设备名, void *data 数据)
{
struct vfsmount *mnt;


if (!type)
return -EINVAL;


/* we need capabilities... */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;


lock_kernel();
mnt = do_kern_mount(type, flags, name, data); 获取新文件系统的vfsmount结构
unlock_kernel();
if (IS_ERR(mnt))
return PTR_ERR(mnt);


return do_add_mount(mnt 新文件系统vfsmount, path 目标路径, mnt_flags, NULL); 将新的文件系统添加到目标文件系统中
}
================================================================
struct vfsmount *do_kern_mount(const char *fstype, int flags, const char *name, void *data)
{
struct file_system_type *type = get_fs_type(fstype); 从全局文件系统链表file_systems中寻找文件系统类型
struct vfsmount *mnt;
if (!type)
return ERR_PTR(-ENODEV);
mnt = vfs_kern_mount(type 文件系统类型, flags 文件系统挂载标志, name 设备名, data 文件系统数据);
//主要调用主体的file_system_typ->get_sb函数或mount函数
if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&!mnt->mnt_sb->s_subtype)
mnt = fs_set_subtype(mnt, fstype);
put_filesystem(type);
return mnt;
}
static struct file_system_type xfs_fs_type = {
.owner = THIS_MODULE,
.name = "xfs",
.get_sb = xfs_fs_get_sb,-->get_sb_bdev(fs_type 文件系统类型, flags 文件系统挂载标志, dev_name 设备名, data 挂载时的文件系统数据, xfs_fs_fill_super,mnt 新分配的vfsmount);
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};

int get_sb_bdev(struct file_system_type *fs_type,int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int),struct vfsmount *mnt)
{
struct block_device *bdev;
struct super_block *s;
fmode_t mode = FMODE_READ;
int error = 0;


if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;
//通过设备名找到对应的块设备block_device,(先通过路径找到inode节点,再通过节点找到设备)
bdev = open_bdev_exclusive(dev_name, mode, fs_type);

/*
* once the super is inserted into the list by sget, s_umount
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
*/
mutex_lock(&bdev->bd_fsfreeze_mutex);
if (bdev->bd_fsfreeze_count > 0) {
mutex_unlock(&bdev->bd_fsfreeze_mutex);
error = -EBUSY;
goto error_bdev;
}
//查找或创建一个指定文件系统类型的超级块,并初始化超级块
s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
mutex_unlock(&bdev->bd_fsfreeze_mutex);

if (s->s_root) {
if ((flags ^ s->s_flags) & MS_RDONLY) {
deactivate_locked_super(s);
error = -EBUSY;
goto error_bdev;
}
close_bdev_exclusive(bdev, mode);
} else {
char b[BDEVNAME_SIZE];
s->s_flags = flags;
s->s_mode = mode;
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
sb_set_blocksize(s, block_size(bdev));
//回调传入的函数,具体文件系统的 填充超级块函数
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
s->s_flags |= MS_ACTIVE;
bdev->bd_super = s;
}
//关联新的vfsmount与 s超级块
simple_set_mnt(mnt, s); //mnt->mnt_sb=s;mnt->mnt_root=dget(s->s_root);
return 0;
}

a_ops 是地址空间address_space对象中的一个关健域。它指向address_space_operations地址空间操作表。
它包含有一组方法(定义了对拥有页面的处理方式)。


writepage:写操作(从page cache写入到磁盘)
readpage :读操作 (从磁盘读入到page缓存)
sync_page:Start the I/O data transfer of already scheduled operations on owner's pages
writepages:把指定数量的脏页写入磁盘。 
set_page_dirty:设置 脏页
readpages: 从磁盘读多个页到page缓存。
write_begin:准备写操作,必要是分配页,加锁返回给VFS.
write_end:表明写操作完成,应解锁页面,更新inode的i_size. 
bmap:从文件块编号找到逻辑块号。
invalidatepage:设置页面无效。
releasepage:被日志文件系统用来准备释放页面。
direct_IO: 直接IO数据传输(绕过页缓存)
get_xip_mem:
migratepage:
launder_page:
is_partially_uptodate:
error_remove_page:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值