mount挂载时 no such device_新一代mount系统调用(5)——fsconfig实现(下之创建根节点)...

132c8821c81c4b5d76f86bc676fa7d56.png

前言

书接上文,我们在前面 fsconfig实现(上) 和 fsconfig实现(下之参数解析) 两篇文章中按照挂载参数解析的逻辑顺序讲解了fsconfig的实现。fsconfig除了做参数解析以外,还有两个重要的命令,FSCONFIG_CMD_CREATE 和 FSCONFIG_CMD_RECONFIGURE。CREATE用于新的挂载,RECONFIGURE则多用于remount。我们下面将讲解 FSCONFIG_CMD_CREATE的逻辑,RECONFIGURE的逻辑可参考CREATE的逻辑自行理解。

我们在fsconfig实现(下之参数解析) 开始的时候就留下了一个伏笔,我们在fsconfig执行到vfs_fsconfig的时候按照参数解析的逻辑分支讲了下去,现在我们将顺着FSCONFIG_CMD_CREATE的逻辑继续看。

按照 新一代mount系统调用(1)——接口初探 中我们给出的用例,我们现在到了这步:

fsfd 

就是使用fsconfig来执行FSCONFIG_CMD_CREATE这步。

vfs_fsconfig_locked - FSCONFIG_CMD_CREATE

static 

上次我们是走的default的分支,去vfs_parse_fs_param里看了一圈。现在我们从case FSCONFIG_CMD_CREATE这个分支开始。

我们在fsopen临近结尾是将fc->phase设置为FS_CONTEXT_CREATE_PARAMS,表示我们下面要做参数解析了。现在我们判断当前是不是这个阶段,实际上我们要判断当前是不是从这个阶段执行过来的,因为我们后面马上要进入下一个phase了。

if 

mount_capable做一些必要的权能检查,不影响主要逻辑。接着就是将当前的阶段设置成为FS_CONTEXT_CREATING,表示我们下面要进入创建superblock的阶段了。就是说我们下面将创建针对当前要挂载的文件系统的内存superblock实例,然后保存在文件系统上下文的fc->root域里。

接下来的一步是最重要的,vfs_get_tree(fc)用于创建(或者获取已有的,我们这里是创建)根节点以及superblock。

关于什么是根节点,以及挂载为什么需要创建根节点和superblock,读者需要在继续下面阅读之前弄懂我在讲解old mount系统调用时将的部分内容,参考 图解mount系统调用之挂载关系 这篇文章,以及其前后相关文章,参考如下索引:

醉卧沙场:README - 专业性文章及回答总索引​zhuanlan.zhihu.com
65123a1ad471e2e790184d058d1d17a4.png

vfs_get_tree

int 

我们在讲fsopen的时候讲了文件系统上下文的fc->root域的作用,我们之前的讲解过程也一直没有用到这个域。现在就是设置这个域的时候了,主要就是通过下面这行代码:

/* Get the mountable root in fc->root, with a ref on the root and a ref                                                                                                                

通过注释我们应该也能看出这行是要干什么,而且看到fc->ops->get_tree的形式我们应该也知道这是一个不同文件系统不同实现的hook函数,我们还是以XFS为例继续看一下XFS(xfs_context_ops)的get_tree方法是如何实现的。

xfs_fc_get_tree

static 

xfs_fc_get_tree调用通用的get_tree_bdev函数,但是给了它一个私有的xfs_fc_fill_super方法让它使用。这个fill_super方法是很多文件系统各自提供的一个用于初始化自己的superblock的方法。

int 

我们讲解一下主要的逻辑,首先:

bdev 

得到文件系统所在设备的实例,为后面需要的时候做一个准备。接着:

fc

将我们上面得到的文件系统所在设备的实例赋给fc->sget_key,用于标识一个superblock。然后下面在调用sget_fc时提供了两个方法,一个是test_bdev_super_fc:

static 

从仅有的这一行逻辑可以看出,它就是判断当前的文件系统上下文所代表的superblock,和*s所代表的superblock是不是同一个,我们下面看到它如何被使用。

而set_bdev_super方法的作用就是设置用当前的文件系统上下文fc,来设置struct super_block *s和设备有关的域。

static 

做了这些铺垫,我们来正式看一下sget_fc。

sget_fs

struct 

首先看if(test),如果我提供了test方法,也就是上面我们说的test_bdev_super_fc方法,下面就通过一个循环来查找是否有一个已经存在的和当前我们所需的superblock对应的superblock实例,这种情况多出现在此文件系统已经挂载了一次的情况。我们第一次挂载,一般没有这样的“方便”,所以我们会进入下一个逻辑if(!s)的逻辑。我们上面没有得到现成的superblock,就要在这里自己创建,通过:

s 

我们知道,alloc只是分配空间和基本初始化(初始化了很多基本的域,可自行翻看alloc_super函数,其逻辑一目了然)。所以下面还要对这个刚alloc的superblock进行更多设置。主要是将我们之前得到的保存在fc中的数据转到superblock里。所以下面我们会看到很多s->s_* = fc->*的代码,以及set(s, fc)就是我们上面说到的set_bdev_super_fc方法。

在superblock设置后,通过:

list_add_tail(&s->s_list, &super_blocks);

将这个superblock加入superblock的一个全局list里。

再通过:

hlist_add_head(&s->s_instances, &s->s_type->fs_supers);

将这个superblock加入这个文件系统实例所对应的superblock的list里。到此细心的人可能发现,我们几乎设置了superblock的所有域,但是还有几个没设置,其中最主要的就是 s->s_root。不过这时 sget_fc 已经返回刚刚得到的superblock实例,我们返回get_tree_bdev继续看。

下面if (s->s_root) 判断,我们不是一个已有的superblock,我们自己新建的superblock,所以这里还没有s->s_root,所以下面要执行else部分的逻辑:

} 

这部分最主要的一步就是fill_super(s, fc)这步,这也是我们上面说的在调用get_tree_bdev时提供的xfs_fc_fill_super方法。xfs_fc_fill_super就是由XFS实现的设置自身superblock的方法,其下面饱含很多XFS独有的逻辑,需要先理解XFS才能明白。我们这里就先不过多展开讲解XFS,维持文章的重心在讲解fsconfig上。所以我列出xfs_fc_fill_super里我们需要知道的一些代码如下:

static 

我们可以看到xfs_fc_fill_super还在持续的初始化着superblock的很多域,最重要的是我们通过xfs_mountfs(mp)得到根inode。在通过sb->s_root =d_make_root(root)得到根dentry,并把它放在superblock的s_root域上。从此返回后,我们就得到了我们所需的根inode,根dentry以及初始化好的superblock。

然后我们返回get_tree_bdev函数,在fill_super结束得到root dentry或,我们执行:

fc

将root dentry也保存在文件系统上下文里。通过root dentry我们也可以方便的找到root inode和superblock,所以这里实际上是让我们日后可以通过fc->root找到这三个东西。

然后get_tree_bdev返回到xfs_fc_get_tree,再返回到vfs_get_tree,继续执行。vfs_get_tree在得到根和superblock后,其主要任务也完成,返回fsconfig继续执行:

case 

从vfs_get_tree返回后我们得到了superblock和根dentry,然后就基本完成了FS_CONTEXT_CREATING的阶段,将阶段设置为FS_CONTEXT_AWAITING_MOUNT,表示我们已经得到了所有我们要得到的东西,包括挂载所需参数和superblock以及根dentry,下面就可以开始准备挂载了,AWAITING_MOUNT顾名思义,就是等待过载。

结语

到此我们就完成了fsconfig的讲解。fsconfig主要完成参数解析和superblock以及root的初始化两方面工作。文件系统上下文作为一个贯穿文件系统挂载始终的临时结构,到这里已经基本上保存了它需要的所有东西,下面我们就要用这些东西进行创建挂载实例,进而挂载文件系统。我们将在下文讲解fsmount时继续说明。到此我们也完成了 一开始 时说的六个步骤中的第三步。

注意我们在前言的尾部提到,如果阅读本文前不能正确认识文件系统各主要结构在挂载时的作用和关系,那么阅读本文以及后面的内容将有困难。所以最好先通过额外的学习前言中提到的文章以及其它文章或代码理解更多内容,再继续下面的学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值