OCFS2文件系统磁盘布局与基本管理


概述

前文已经大概介绍过OCFS2的部署和应用场景,本文及后续文章重点介绍OCFS2文件系统的具体实现。为了便于后续代码的理解,本文首先介绍一下该文件系统关键数据的磁盘布局情况。理解磁盘布局是理解OCFS2文件系统的基础,只有理解了布局,才能更好的理解代码中的各种处理流程。

本文介绍基于Linux4.1.12内核,其它版本内核可能稍有不同,但不影响理解。
本文示例文件系统格式化采用默认参数,也即4K逻辑块大小和128K簇块大小

本文首先介绍文件系统在整个磁盘的布局情况,然后介绍文件夹内数据文件内数据的布局。整体原则是从整体到局部,从轮廓到细节的顺序。

整体磁盘布局

整体布局主要介绍OCFS2文件系统如何实现对整个磁盘的管理。如下图OCFS2文件系统与Ext4文件系统类似,将磁盘划分为若干组进行管理,Ext4文件系统叫块组(block group),这里成为簇组(cluster group),虽然概念不同,但大体用途基本一致。如果不了解Ext4文件系统也没有关系,下图能很清楚的说明磁盘的整体布局情况。如图所示最上面方框(第一行方框)表示的是簇组(cluster group),分别是Cluster Group0、Cluster Group1等等。对于文件系统将磁盘划分为簇组(可以简单理解为组)类似于超市将一层楼的空间划分为若干个货架来摆放货物,而不是堆到一起。通过货架来摆放物品明显可以提高货物查找的便捷性。

图1\. 磁盘布局总图

如上图所示除了第一个簇组(Cluster Group0)比较特殊之外,其它簇组都是一样的,也就是最前面一个块是簇组描述信息,其后为数据簇(Cluster),也就是被管理的单元。第一个簇组特殊的原因是其中包含了很多元数据(管理数据),包括文件系统的超级块、系统文件夹和系统文件等内容,但管理的原理是一致的。

OCFS2在管理磁盘空间时同时采用两种管理单元,一种叫做逻辑块,大小范围从512B到4K,大小必需是512B的2的幂整数倍(也即512B、1K等以此类推);另外一种叫簇组,大小范围是4KB到1MB,大小必需是4KB的2的幂整数倍。

如下图行所示为管理磁盘空间的基本原理。在簇组的最前面有一个簇组描述信息,其中一部分是位图(Bitmap),位图的每一位(Bit)与该空间的一个簇对应,如果对应的位为1,则标明相应的簇已经分配出去了,如果为0则说明没有被使用。因此文件系统可以根据位图中的相应来确认那些簇是可以使用的。

图2\. 磁盘管理原理

前文已述,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模式

inline模式比较简单,数据就存储在inode的内部,其位置是通过inode成员遍历id2确定。该成员是一个联合体,在不同的场景下类型不同,在文件夹inline模式下为一个ocfs2_inline_data的结构体,具体如图所示。

图3\. inline模式文件夹inode格式

id2对象内部成员id_count表示该文件夹内部项目的数量,id_data指向具体存储文件夹内部项目的信息。具体项目是通过一个名为ocfs2_dir_entry的结构体描述的。文件夹内部的这些项目线性的排布在id_data分配的存储空间中。如图是文件夹内部项目排布示意图和ocfs2_dir_entry结构体定义。这里需要重点说明的是ocfs2_dir_entry的rec_len成员,这里记录了该结构体的长度,这样根据起始位置id_data和前一个成员的长度,就能找到下一个成员的位置,也即进行项目的遍历。

图4\. 数据排布示意图

extent模式

在extent模式则相对复杂一些,该种模式下extent其实是以B+树的方式存储文件夹内部的数据的。关于B+树的概念超出了本文的范围,具体实现请参考其它文章,本文仅仅介绍该种场景下文件夹数据的布局情况。如前文所示,不同的模式下inode的id2成员的类型不同,在extent模式下,该成员为ocfs2_extent_list类型的结构体。此时该inode的结构体定义如图所示。

图5\. extent模式文件夹inode格式

对于文件夹数据所组成的B+树,是以ocfs2_dinode为根的一颗树,如下图灰色虚线指示的为树的父子节点之间的关系。红色虚线指示的是对结构体的进一步细化。本例中为B+树的高度为2,其中树根指向下一级节点,该级节点全部为叶子节点。叶子节点中有相关的记录项,记录了逻辑位置与磁盘物理位置的关系,而此时物理块的 数据就是目录项。实际情况可能树高可能为1,此时inode中的id2成员中的数据记录了逻辑位置与磁盘物理位置的关系。也可能树高更改,此时中间层存储的映射到的物理块并不是存储目录项的内容,而是进一步的映射关系。

图6\. 数据排布示意图

在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类型的成员,通过其内部的记录可以指向下一级节点(非叶子节点场景),或者其本身就可以指向存储文件夹数据的磁盘块(叶子节点场景)。

文件内数据

文件内数据的存储方式与文件夹类似,也存在这两种模式。文件的数据布局的基本原理与文件夹是一样的,差异是其中存储的是文件的具体数据。具体实现可以阅读代码,本文不在赘述。

关注作者微信公众号,更及时的获取原创IT技术文章。
公众号二维码