前文已经大概介绍过OCFS2的部署和应用场景,本文及后续文章重点介绍OCFS2文件系统的具体实现。为了便于后续代码的理解,本文首先介绍一下该文件系统关键数据的磁盘布局情况。理解磁盘布局是理解OCFS2文件系统的基础,只有理解了布局,才能更好的理解代码中的各种处理流程。
本文介绍基于Linux4.1.12内核,其它版本内核可能稍有不同,但不影响理解。
本文示例文件系统格式化采用默认参数,也即4K逻辑块大小和128K簇块大小
本文首先介绍文件系统在整个磁盘的布局
情况,然后介绍文件夹内数据
和文件内数据
的布局。整体原则是从整体到局部,从轮廓到细节的顺序。
整体布局主要介绍OCFS2文件系统如何实现对整个磁盘的管理。如下图OCFS2文件系统与Ext4文件系统类似,将磁盘划分为若干组进行管理,Ext4文件系统叫块组(block group),这里成为簇组(cluster group),虽然概念不同,但大体用途基本一致。如果不了解Ext4文件系统也没有关系,下图能很清楚的说明磁盘的整体布局情况。如图所示最上面方框(第一行方框)表示的是簇组(cluster group),分别是Cluster Group0、Cluster Group1等等。对于文件系统将磁盘划分为簇组(可以简单理解为组)类似于超时将一层楼的空间划分为若干个货架来摆放货物,而不是堆到一起。通过货架来摆放物品明显可以提高货物查找的便捷性。
如上图所示除了第一个簇组(Cluster Group0)比较特殊之外,其它簇组都是一样的,也就是最前面一个块是簇组描述信息,其后为数据簇
(Cluster),也就是被管理的单元。第一个簇组特殊的原因是其中包含了很多元数据(管理数据),包括文件系统的超级块、系统文件夹和系统文件等内容,但管理的原理是一致的。
OCFS2在管理磁盘空间时同时采用两种管理单元,一种叫做逻辑块,大小范围从512B到4K,大小必需是512B的2的幂整数倍(也即512B、1K等以此类推);另外一种叫簇组,大小范围是4KB到1MB,大小必需是4KB的2的幂整数倍。
如下图行所示为管理磁盘空间的基本原理。在簇组的最前面有一个簇组描述信息,其中一部分是位图(Bitmap),位图的每一位(Bit)与该空间的一个簇对应,如果对应的位为1,则标明相应的簇已经分配出去了,如果为0则说明没有被使用。因此文件系统可以根据位图中的相应位
来确认那些簇是可以使用的。
前文已述,OCFS2第一个簇组(Cluster Group0)相对特殊,主要是包含很多元数据。如图1所示,主要包含如下几部分内容:
预留块
:在磁盘最开始的2个逻辑块为预留块,这个主要是为了与第一版本(OCFS)进行区分,因为两者是完全不兼容的。簇组描述符
:簇组描述符是一个数据结构,里面包含描述簇组的所有信息,包含该簇组的使用情况、可用位的数量和本描述的偏移等等信息。数据簇
:实际存储数据的部分了解了这些基本概念之后,还有一个问题没有解决。那就是簇组的大小是如何确定的呢?前文我们已经知道簇组通过其前面的簇组描述符进行管理,而该描述符默认占用一个块(4K)的空间,而该描述符前面基本描述信息占了64B,因此位图剩余的可用空间为4032(4096-64)B,也就是大3225位(Bit),因此最多可以管理32256个簇,也即4032M(32256*128KB)。
另外,OCFS2还有一个本地管理的概念,由于OCFS2是集群文件系统,为了保证各个节点的协同,必然需要一种跨节点的网络锁(分布式锁),这样势必造成文件系统整体性能的下降。因此OCFS2在设计的时候增加了一个本地分配的功能,其基本原理是预先占用全局分配中的一块区域,然后在本节点内独自对该空间进行管理。
对于本地分配的最大管理空间,由于使用的ocfs2_dinode进行管理(后面详述原理),也是占用1个块(4K),前面描述信息占用了208B,因此剩余的空间可以管理的最大空间为3888M。上文是以128K簇为例描述的,不同簇大小,簇组大小和本地分配的最大空间会有相应的变化,具体如下表所示。
cluster size | group size | local alloc |
---|---|---|
4K | 126M | 121M |
8K | 252M | 243M |
16K | 504M | 486M |
32K | 1008M | 972M |
64K | 2016M | 1944M |
128K | 4032M | 3888M |
256K | 8064M | 7776M |
512K | 16128M | 15552M |
1024K | 32256M | 31104M |
上面一节主要描述了OCFS2文件系统关于磁盘布局的基本内容及涉及的几个关键概念。本节将介绍一下该文件系统是如何对磁盘空间进行管理的。OCFS2比较特殊的地方在于,其都是通过inode进行管理的,每种不同的资源有不同的inode。在该文件系统中有一个用户看不到的文件夹,这里成为系统文件夹
,其中存储这管理用的inode,也就是本文件系统的基本元数据。具体如表所示,本表不是全量,选择几个关键的inode进行介绍。
inode编号 | 名称 | 描述 |
---|---|---|
65 | 根目录 | 这个是本文件系统的根目录,文件系统挂载后呈现给用户的根目录 |
66 | 系统目录 | 本文件系统的管理目录,这个目录对用户不可见,用于实现对磁盘空间的管理 |
68 | global_inode_alloc | 系统inode分配管理的inode,也就是该inode用于管理系统inode分配和回收 |
71 | global_bitmap | 全局位图,用于实现对簇组簇的全局管理,访问时需要通过分布式锁进行保护 |
80 | extent_alloc:0000 | 元数据分配,带有0000是集群节点相关的,具体数量与槽位数相同,例如0000,0001等 |
88 | inode_alloc:0000 | 用于本地inode的分配管理,这个是用户的inode |
104 | local_alloc:0000 | 该inode用于实现本地磁盘空间的管理 |
本文首先介绍文件夹是因为文件系统挂载后,首先呈现给用户的就是一个文件夹。挂载成功后,用户可以在其上创建文件,写读数据。文件名称和子文件夹其实就是文件夹内的数据,因此首先介绍文件夹的数据布局。
文件夹中数据的存储有两种模式,如果开启了inline-data特性,那么起始情况下这些数据(文件名称和inode等信息)是存放在文件夹的inode的所在的区域内的。由于一个inode默认情况下占用4K的空间,因此对于文件数量不太多的文件夹,通过这块区域就可以存储,不需要额外申请空间。如果在文件夹中有海量文件的情况下,inode节点空间不足以存储这些信息,此时就会通过extent的方式存储这些数据。另外,为了便于文件夹内文件的检索,OCFS2有实现了一个索引树,可以通过该索引树快速检索文件。
inline模式比较简单,数据就存储在inode的内部,其位置是通过inode成员遍历id2确定。该成员是一个联合体,在不同的场景下类型不同,在文件夹inline模式下为一个ocfs2_inline_data的结构体,具体如图所示。
id2对象内部成员id_count表示该文件夹内部项目的数量,id_data指向具体存储文件夹内部项目的信息。具体项目是通过一个名为ocfs2_dir_entry的结构体描述的。文件夹内部的这些项目线性的排布在id_data分配的存储空间中。如图是文件夹内部项目排布示意图和ocfs2_dir_entry结构体定义。这里需要重点说明的是ocfs2_dir_entry的rec_len成员,这里记录了该结构体的长度,这样根据起始位置id_data和前一个成员的长度,就能找到下一个成员的位置,也即进行项目的遍历。
在extent模式则相对复杂一些,该种模式下extent其实是以B+树的方式存储文件夹内部的数据的。关于B+树的概念超出了本文的范围,具体实现请参考其它文章,本文仅仅介绍该种场景下文件夹数据的布局情况。如前文所示,不同的模式下inode的id2成员的类型不同,在extent模式下,该成员为ocfs2_extent_list类型的结构体。此时该inode的结构体定义如图所示。
对于文件夹数据所组成的B+树,是以ocfs2_dinode为根的一颗树,如下图灰色虚线指示的为树的父子节点之间的关系。红色虚线指示的是对结构体的进一步细化。本例中为B+树的高度为2,其中树根指向下一级节点,该级节点全部为叶子节点。叶子节点中有相关的记录项,记录了逻辑位置与磁盘物理位置的关系,而此时物理块的 数据就是目录项。实际情况可能树高可能为1,此时inode中的id2成员中的数据记录了逻辑位置与磁盘物理位置的关系。也可能树高更改,此时中间层存储的映射到的物理块并不是存储目录项的内容,而是进一步的映射关系。
在extent模式下一共涉及4种数据结构,分别是ocfs2_inode、ocfs2_extent_block、ocfs2_extent_list和ocfs2_extent_rec。其中ocfs2_extent_list是树中一个节点维护记录列表的数据结构,其中l_recs成员是一个ocfs2_extent_rec类型的数组,每一项记录了一个映射关系(逻辑地址到磁盘物理地址)。ocfs2_extent_block结构体可以理解为B+树非根节点的描述,其中也包含一个ocfs2_extent_list类型的成员,通过其内部的记录可以指向下一级节点(非叶子节点场景),或者其本身就可以指向存储文件夹数据的磁盘块(叶子节点场景)。
文件内数据的存储方式与文件夹类似,也存在这两种模式。文件的数据布局的基本原理与文件夹是一样的,差异是其中存储的是文件的具体数据。具体实现可以阅读代码,本文不在赘述。
关注作者微信公众号 itworld123,更及时的获取原创IT技术文章。