您的位置:首页 > 其它

mount过程分析之四(vfs_kern_mount->mount_fs->xfs_fs_mount)

2014-10-14 18:01 531 查看

sys_mount - > do_mount -> do_new_mount -> vfs_kern_mount

vfs_kern_mount的作用就是准备好一个完整的mount结构。

vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct mount *mnt;
struct dentry *root;

if (!type)
return ERR_PTR(-ENODEV);

// alloc一个新的struct mount结构,并初始化里面一部分(如链表指针、mnt_devname等成员内容)
mnt = alloc_vfsmnt(name);
if (!mnt)
return ERR_PTR(-ENOMEM);

if (flags & MS_KERNMOUNT)
mnt->mnt.mnt_flags = MNT_INTERNAL;

// 调用具体文件系统的mount回调函数type->mount,继续挂载操作
root = mount_fs(type, flags, name, data);
if (IS_ERR(root)) {
mnt_free_id(mnt);
free_vfsmnt(mnt);
return ERR_CAST(root);
}

// 完成mnt结构的最后赋值,并返回vfsmount结构
mnt->mnt.mnt_root = root;
mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
lock_mount_hash();
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
unlock_mount_hash();
return &mnt->mnt;
}


vfs_kern_mount主要完成三件事:

1. alloc_vfsmnt创造一个新的struct mount结构

2. 在mount_fs函数里调用特定文件系统的mount回调函数构造一个root dentry,包含特定文件系统的super block信息

3. 用第二步得到的结果完成对struct mount的构造,返回vfsmnt结构。

那么可以看出mount_fs函数就是下一个要叙述的函数了。

sys_mount - > do_mount -> do_new_mount -> vfs_kern_mount -> mount_fs

这个函数看似复杂,其实主要就做一件事,调用type->mount回调函数。我们前面说过这个回调函数是在每个文件系统类型注册到内核中时实现的一个mount函数,它的前身是get_sb()函数,都是为了完成针对特定文件系统特点的操作而个别实现的回调函数。

除了type->mount之外,还有很多安全检查地方,这里就先不多说了。来看一下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;
char *secdata = NULL;
int error = -ENOMEM;

if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
secdata = alloc_secdata();
if (!secdata)
goto out;

error = security_sb_copy_data(data, secdata);
if (error)
goto out_free_secdata;
}

// 这里就是调用file_system_type的mount回调函数的地方,每个文件系统都有自己实现的mount回调函数
root = type->mount(type, flags, name, data);
if (IS_ERR(root)) {
error = PTR_ERR(root);
goto out_free_secdata;
}
sb = root->d_sb;
BUG_ON(!sb);
WARN_ON(!sb->s_bdi);
WARN_ON(sb->s_bdi == &default_backing_dev_info);
sb->s_flags |= MS_BORN;

error = security_sb_kern_mount(sb, flags, secdata);
if (error)
goto out_sb;

/*
* filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE
* but s_maxbytes was an unsigned long long for many releases. Throw
* this warning for a little while to try and catch filesystems that
* violate this rule.
*/
WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
"negative value (%lld)\n", type->name, sb->s_maxbytes);

up_write(&sb->s_umount);
free_secdata(secdata);
return root;
out_sb:
dput(root);
deactivate_locked_super(sb);
out_free_secdata:
free_secdata(secdata);
out:
return ERR_PTR(error);
}


mount再往下就是每个文件系统自己实现的mount回调函数了,我们以xfs为例说明。在fs/xfs目录下可以找到xfs文件系统的实现代码。xfs_super.c中可以找到init_xfs_fs模块初始化函数,里面调用了我们最开始提到的register_filesystem(&xfs_fs_type)函数,参数xfs_fs_type就是xfs实现的file_system_type结构。我们已经讲述了xfs_fs_type的定义(http://blog.csdn.net/zr_lang/article/details/39963253),现在我们要着重说一下xfs_fs_mount()函数。

sys_mount - > do_mount -> do_new_mount -> vfs_kern_mount -> mount_fs -> xfs_fs_mount

xfs_fs_mount是xfs自己实现mount回调函数,其实现就是调用mount_bdev()函数,如下:

STATIC struct dentry *
xfs_fs_mount(
struct file_system_type *fs_type,
int                     flags,
const char              *dev_name,
void                    *data)
{
return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
}


但是这里有一个需要注意的地方就是mount_bdev虽然是一个通用函数,但是其最后一个参数是一个函数指针,xfs传入xfs_fs_fill_super作为参数。xfs_fs_fill_super是xfs实现的一个只适用于xfs的函数,也就是这里还是需要一个每个文件系统各异的处理函数。下面将分别对mount_bdev和xfs_fs_fill_super两个函数进行分析。
http://blog.csdn.net/zr_lang/article/details/40325241 (mount 七)
http://blog.csdn.net/zr_lang/article/details/40343899 (mount 六)
http://blog.csdn.net/zr_lang/article/details/40115013 (mount 五)
http://blog.csdn.net/zr_lang/article/details/40080979 (mount 四)
http://blog.csdn.net/zr_lang/article/details/40049305 (mount 三)
http://blog.csdn.net/zr_lang/article/details/40002285 (mount 二)
http://blog.csdn.net/zr_lang/article/details/39963253 (mount 一)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: