EXT2的文件系统装载之内核函数ext2_fill_super分析

来源:互联网 发布:毕向东35天java教学 编辑:程序博客网 时间:2024/05/21 01:51
    在安装ext2fs的时候,存放ext2文件系统的磁盘分区上的大部分数据结构的信息都会被拷贝到RAM(操作系统内存)中,从而使得内核避免了许多后续的操作,变得简单。由于ext2磁盘数据结构都保存在ext2磁盘分区的块中,所以当需要经常更新一些数据结构时,内核会利用页高速缓存来实现。

在实际mount一个文件系统的时候,ext2文件系统依赖于虚拟文件系统的一个标准函数(mount_bdev)来实现文件系统信息的装载。

由这个函数调用参数来看,安装ext2文件系统的时候最终会调用ext2_fill_super()函数来为super_block数据结构分配空间,并写入从磁盘读取的数据。ext2_fill_super()可以说是装载文件系统信息的时候的一个非常关键和核心的函数,它在fs/ext2/super.c中定义,关于改函数的代码总共有380多行,完全在此展现不恰当,但是,从对mount_bdev()的调用中可以看出,是将指向ext2_fill_super的一个函数指针传递给了mount_bdev,ext2_fill_super函数是用来填充VFS中一个超级块对象,如果内存中没有适当的超级块对象,数据就必须从硬盘读取。因此,可以说关于文件系统的装载过程主要知道ext2_fill_super函数就可以了。下面分析关于该函数源码:

首先有必要解释一下部分重要的设定的参数:

bh:指向页高速缓冲区首部的指针;

sbi:代表内存中ext2文件系统的超级块信息

es:磁盘上的ext2文件系统的超级块

root:VFS中的inode信息

要理解这个函数的实现,就要先理解页高速缓存。关于这部分我主要是看了这篇博文:http://blog.csdn.net/yunsongice/article/details/5850656。主要分析两大块的内容:如何将块存入页高速缓存以及如何从页高速缓存中搜索块。看了这两部分,了解了页高速缓存的工作机制和原理之后,在继续分析ext2_fill_super就稍微容易些了。

不过在整理ext2的超级块和块组中组描述符数据结构与页缓冲区的关系之前,有必要找出ext2在内存中的superblock数据结构中与缓冲区有关的域和字段:

(1)struct buffer_head * s_sbh;//这个指针指向包含磁盘超级块的缓冲区的缓冲区首部

(2)struct ext2_super_block * s_es;//该指针指向磁盘超级块所在的缓冲区

(3)unsigned long s_desc_per_block;//表示块组描述符的个数,可以存放在一个块中

(4)struct buffer_head ** s_group_desc;//这是一个二级指针,指向一个包含组描述符的缓冲区首部指针的数组。

关于ext2的超级块及块组描述符和缓冲区之间的关系可以大致描述为下图:

之前也有说到,当内核安装ext2文件系统的时候(mount命令),它会调用ext2_fill_super函数来为数据结构分配内存空间,并写入从磁盘读取的数据。

在前面已经列出了ext2_fill_super()函数中的相关变量的定义,接下来先画出该函数的代码流程:


具体解释:

首先用kzalloc分配一个内存中exct2文件系统的超级块描述符,将其地址作为参数传递并存放在超级块sbs_fs_info字段中。事实上,ext2_fill_super()首先会设置一个初始的块大小,用来读取超级块,而由于文件系统中使用的块的大小此时并不知晓,所以内核首先会通过sb_min_blocksize查找最小的可能值。若块设备使用的最小块大小比sb_min_blocksize所设置的大,那么就设用块设备的设置。

接下来使用sb_bread读取超级块所在的数据块。实际上sb_bread__bread函数的一个包装。然后就是要检查,以确保目前的分区实际上是不是包含了一个ext2文件系统。超级块中存储的magic域就保存了这部分检查所需要的信息。其值必须与EXT2_SUPER_MAGIC匹配。

parse_options用来分析用于指定装载选项的参数是否正确,在这步操作之前所有的值都设置为默认值,用以确保假如不知定选项,就等价于指定默认选项。

对文件系统特性的检查能够揭示内核是否能够装载改文件系统。、

如果保存在s_blocksize中的文件系统的块大小和最初指定的最小值并不匹配,那么使用sb_set_blocksize修改最初设置的块大小,并再次读取超级块所在的数据块。如果块大小与传输数据所用的块的大小相等,那么就可以使得内核的工作变简单很多,就可以一步读出一个文件系统块信息。

文件系统的元数据信息一直留在内存中,由ext2_sb_info数据结构来保存。元数据其实就是一些简单的值,只需要将数据从磁盘复制到数据结构对应的成员域即可。

接下来是读入文件系统的块组的组描述符的信息,并且使用ext2_check_descriptor检查一致性。

为了提高块分配的性能,ext2文件系统采用了一种称作预分配的机制,在这里就是在预留窗列表中添加了一项新的预留区,可以把预分配当作是最后块分配之前的一个附加层,用来判断如何充分利用可用空间。不过,预分配只是一个建议,真正的分配才是最终决定。

填充超级块的最后一步就是ext2_count_blocks,ext2_count_inodes,ext2_count_dirs分别计算空闲块、空闲inode以及空闲目录的数目。不过需要注意的是,这些值时报存在近似的计数器中,其初始值是正确的,但是在运转期间可能会有轻微的偏离。

然后,将控制权转交给ext2_setup_super,由它进行最后的检查并输出适当的警告信息,最后由ext2_write_super将超级块的内容写回到底层的存储介质上。
参考资料:
http://blog.csdn.net/yunsongice/article/details/5819323

0 0
原创粉丝点击