分享
 
 
 

JFS文件系统原理--JFS布局

王朝other·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

日志文件系统如何处理磁盘布局

Steve Best,Linux 技术中心,IBM

Dave Kleikamp,Linux 技术中心,IBM

本文描述磁盘日志文件系统(JFS)布局,以及使用磁盘布局结构来实现可扩展性、可靠性和性能的机制。还会了解用来操作这些结构的策略和算法,以及 JFS 是在哪里使用遍布文件系统的 B+ 树来提高文件系统操作性能。

JFS 体系结构可通过其磁盘布局特性的上下文进行说明。磁盘布局是 JFS 用来控制文件系统的格式。本文讨论盘区的文件几何构造、目录格式、块分配映射表格式、inode 和布局结构的其它特性。本文还提供了文件布局使用的 B+ 树数据结构的细节和示例。选择 B+ 树是为了提高读写盘区的性能,这是 JFS 执行的最普通操作。

分区、聚集、分配组、文件集

这里是磁盘布局的“全景图”。

分区

JFS 文件系统建立在分区上,分区是由 FDISK 导出到 JFS 的抽象。

分区有:

固定分区块尺寸,其合法值为 512、1024、2048 或 4096 字节。分区块尺寸定义了分区上支持的最小 I/O 单元。这对应于组成分区的物理设备的基本磁盘扇区大小,最普遍的尺寸是 512 字节。

大小为:PART_NBlocks,是分区磁盘块数。

分区磁盘块的抽象地址空间 [ 0.. PART_NBlocks - 1 ]。

聚集

为了支持 DCE DFS(分布式计算环境分布式文件系统),JFS 将磁盘空间分配池(称为聚集)的概念, 与可安装的文件系统子树(称为文件集)的概念分开。本文中聚集和文件集的术语与其 DFS 用法一致。每个分区刚好只有一个聚集;每个聚集可能有多个文件集。在第一个发行版中,JFS 仅支持每个聚集一个文件集;但是,所有元数据都已设计成适用于所有情况。

图 1 显示带有两个文件集的聚集的布局。

聚集有:

在此聚集的开始部分有 32K 保留区域。

固定的聚集块尺寸,其合法值为 512、1024、2048 或 4096 字节,但不小于分区块尺寸。聚集块尺寸定义了聚集上支持的最小空间分配单元。不要把它与分区块尺寸混淆起来,后者定义的是 I/O 的最小单元。

主聚集超级块和辅助聚集超级块。超级块包含聚集方面的信息,例如:聚集的大小、分配组的大小、聚集块的尺寸等等,辅助聚集超级块是主聚集超级块的直接副本。如果主聚集超级块损坏,则使用辅助聚集超级块。这些超级块位于固定位置。这使得 JFS 不依赖任何其它信息,就能够找到它们。超级块结构在 jfs_superblock.h 的 struct jfs_superblock 中定义。

聚集 inode 表,包含描述聚集范围的控制结构的 inode 。聚集 inode 表逻辑上包含一个 inode 数组。聚集无目录结构;在聚集或文件集名字空间中,任何地方都没有聚集 inode 。

辅助聚集 inode 表,包含从聚集 inode 表复制的 inode 。由于对任何文件系统信息的查找而言,聚集 inode 表中的 inode 都是至关重要的,所以它们每一个在辅助聚集 inode 表中都有备份。当然,不会复制 inode 的实际数据,而只是复制可用来查找数据和 inode 本身的寻址结构。

聚集 inode 映射表,描述聚集 inode 表。聚集 inode 分配映射表包含聚集 inode 上及其磁盘位置上的分配状态信息。

辅助聚集 inode 映射表,描述辅助聚集 inode 表。由于必须复制聚集 inode 表本身,辅助聚集 inode 映射表实际上是与聚集 inode 分配映射表分开的映射结构。

块分配映射表,描述在聚集内分配和释放聚集磁盘块的控制结构。块分配映射表在聚集磁盘块内进行一对一映射。

fsck 工作区(未在图 1 中显示),它为 fsck 提供用来跟踪聚集块分配的空间。因为 JFS 支持超大聚集,所以这一区域是必需的;当 fsck 运行时,可能没有足够的内存用来跟踪内存中的这些信息。超级块描述了这一区域。每个聚集块需要一位。fsck 工作区总是存在于聚集的末端。

内嵌日志(未在图 1 中显示)为记录聚集中的元数据更改提供了空间。超级块描述了这一区域。内嵌日志总是紧跟 fsck 工作空间后。

初始情况下,在聚集创建时分配了第一个 inode 盘区。按需要动态分配和释放其它 inode 盘区。每个聚集 inode 描述聚集本身的某些方面,如下:

保留聚集 inode 0。

聚集 inode 1,即自身 inode ,描述包括聚集 inode 映射表的聚集磁盘块。这是一种循环表示法,因为聚集 inode 1 本身也在自己所描述的文件中。可通过强制规定至少第一个聚集 inode 盘区要在众所周知的位置,即主聚集超级块后面 4K 的位置,来处理以上显而易见的循环表示法问题。因此,JFS 能轻而易举地找到聚集 inode 1,从聚集 inode 1,通过跟随 inode 1 中的 B+ 树,能找到聚集 inode 表的余下 inode 。

要复制聚集 inode 表,JFS 还需要找到聚集 inode 1 的副本,以查找所复制表的其余部分。超级块会包含一个盘区描述符,该描述符描述辅助聚集 inode 表的第一个 inode 盘区的位置。JFS 能够从中找到辅助聚集 inode 1,以及辅助聚集 inode 表的余下部分。

聚集 inode 2 描述块分配映射表。

聚集 inode 3 描述安装时的内嵌日志。虽然分配了 inode ,但无数据存入磁盘。

聚集 inode 4 描述在聚集格式化期间发现的坏块。在块映射表中这些标记成已分配。该 inode 是数据为坏块的普通文件。

保留聚集 inode 5 到 15 以备将来扩展。

从聚集 inode 16 开始,每个文件集有一个 inode ,即文件集分配映射表 inode 。这个 inode 描述了表示文件集的控制结构。当更多文件集添加到聚集中时,为了容纳更多的文件集 inode ,聚集 inode 表本身可能必须增大。

分配组

分配组(AG)把聚集中的空间分成大块,并且允许 JFS 资源分配策略使用众所周知的方法,来实现更好的 JFS I/O 性能。首先,分配策略尝试将相关数据的磁盘块和磁盘 inode 集群起来,使磁盘实现好的局域性。文件通常是顺序地读写,而目录中的文件通常一起访问。其次,为了容纳局域性,分配策略尝试在整个聚集中分配不相关数据。聚集内的分配组用从 0 开始的 AG(分配组)索引。即用 AG 标识。

必须选择分配组大小,以使 AG 足够大以不断提供连续资源分配。为了将聚集扩充或缩小时所需进行的更新数最小化,分配组必须限制最大组数 128。此外,JFS 将对 8192 个聚集块的分配组大小规定其最小值。分配组大小必须总是 1 个 dmap 页(1、2、4、8、 ...dmap 页)描述的块数的 2 的幂次方。分配组大小在聚集超级块中存储。

大小不是分配组大小倍数的聚集将包含部分分配组;磁盘块没有完全覆盖聚集的最后一个分配组。除了JFS 将标记在块分配映射表中分配的却不存在的磁盘块之外,该部分分配组将被当作完整的分配组。

文件集

文件集是文件和目录的集合,这些文件和目录形成了可独立安装的子树。文件集完全包含在一个聚集中。请注意,一个聚集中可能有多个文件集;在那种情况下,所有文件集共享由聚集控制结构定义的空闲聚集磁盘块公共池。

图 2 显示在一个聚集中包含两个文件集的布局。

文件集有:

文件集 inode 表,包含描述文件集范围的控制结构的 inode 。文件集 inode 表逻辑上包含一个 inode 数组。

文件集 inode 分配映射表,描述文件集 inode 表。文件集 inode 分配映射表包含文件集 inode 上及其磁盘位置上的分配状态信息。描述文件集分配映射表和其他文件集信息的超级 inode ,驻留前面所描述的聚集 inode 表中。由于复制了聚集 inode 表,因此这个 inode 存在第二个版本,它指向同样的数据。超级 inode 本身是一个文件。当文件集一开始创建时,分配第一个 inode 盘区按需要动态分配和释放其它 inode 盘区。

文件集中 inode 的分配如下所示:

保留文件集 inode 0。

文件集 inode 1 包含附加的文件集信息,它们无法放入聚集 inode 表中的文件集分配映射表 inode 。

文件集 inode 2 是文件集的根目录 inode 。注意,JFS 保留了 inode 2 是文件系统的根这一公共 Unix 约定。

文件集 inode 3 是文件集的 ACL 文件。

从文件集 inode 4 开始,文件集 inode 用于一般文件集对象、用户文件、目录和符号链接。

盘区、inode 、B+ 树

盘区是当作单元分配给 JFS 对象的连续聚集块序列。盘区完全包含在一个聚集(并且因此也是在一个分区)中;但是,大盘区可能跨多个分配组。

每个 JFS 对象可用一个 inode 来表示。inode 包含预期的对象特定信息,例如:时间戳和文件类型。它们还包含记录盘区分配的 B+ 树。注意,所有 JFS 元数据结构(除超级块之外)都以文件表示。通过重用这种数据的 inode 结构,数据格式(即磁盘布局) 自然是可扩展的。

盘区、B+ 树、inode 在以下章节中详细描述。

盘区

文件是按盘区顺序分配的。盘区是当作一个单元分配的聚集块的连续变长序列。盘区的尺寸范围是 1 到 2(24)-1 个聚集块。盘区可能跨越多个分配组(AG)。为了在插入新盘区、定位特定盘区等操作方面有更优性能,这些盘区是按 B+ 树索引的。

定义一个盘区需要两个值,即其长度和其地址。长度以聚集块尺寸为单位计算。JFS 使用 24 位值来表示盘区的长度,因此盘区的范围大小是 1 到 2(24)-1 个聚集块。

对于 512 字节的聚集块尺寸 (所允许的最小值),最大盘区是512*(2(24)-1)字节,(比 8G 稍小)。对于 4096 字节的聚集块尺寸(所允许的最大值),盘区的最大长度是 4096*(2(24)-1)字节,(比 64G 稍小)。这些限制仅适用于一个的盘区;对整体文件大小没有限制作用。地址指的是盘区中第一个块的地址。地址同样以聚集块为单位:它从聚集的开始处计算块偏移量。

结合了用户特定聚集块尺寸的基于盘区的文件系统,允许 JFS 不需要单独支持内部存储碎片。可配置聚集使用小的聚集块尺寸(例如,512 字节),以使大量小尺寸文件的聚集内部存储碎片最小化。

通常,JFS 分配尝试通过分配最小数量的盘区策略,而使每个盘区尽可能大。这就允许大的 I/O 传送,结果使得性能提高。然而,对于特殊情况,不一定总有这种结果。例如,一个段的写入时复制会造成连续盘区被分割成更小的连续盘区系列。另一种情况是盘区大小的限制。例如:由于 JFS 必须把整个盘区读入内存,然后进行解压缩,所以压缩文件盘区大小是有限的。由于 JFS 的可用内存数量有限,因此它必须保证有足够的空间用于解压缩盘区。

提供了一个碎片整理实用程序,以减少动态分配/释放可变长盘区时出现的外部存储碎片。这种分配和释放可能导致不相连的变长空闲盘区遍及整个聚集。碎片整理实用程序会把多个小的空闲盘区合并成一个较大的盘区。

inode

JFS 磁盘 inode 是 512 字节。一个 JFS 磁盘 inode 包含 4 组基本信息。第一组描述 JFS 对象的 POSIX 属性。第二组描述 JFS 对象的其它属性;这些属性包括支持 VFS 必需的信息、操作系统环境特定的信息、以及 B+ 树的头部。第三组不是包含 B+ 树根节点的盘区分配描述符就是包含内嵌数据。第四组包含扩展属性、更多内嵌数据或附加的盘区分配描述符。在 jfs_dinode.h 的 struct dinode 中定义磁盘 inode 结构。

JFS 动态分配 inode 提供的好处如下:

inode 磁盘块可放在任何磁盘地址,这使得 inode 号和位置分开。这种分离简化了支持聚集和文件集重组,能够使聚集缩小。可以移动 inode ,移动后号码仍然相同。这允许 JFS 不必需要查找目录结构就可以更新 inode 号。对于支持 DFS 文件集复制而言,这种分离也是必需的。当复制文件集时,仅复制 inode 。既然 JFS 能把新的 inode 放在磁盘的任意位置,新 inode 将有与从它们复制的 inode 相同的号码。这允许 JFS 不需复制目录结构并且更新 inode 号。

不再需要分配实际所需十倍的 inode 。这对于 JFS 中较大的 inode 尺寸(大于 512 字节)而言,尤为重要。

大文件的文件分配可能消耗多个分配组且仍是连续的,而静态分配造成间隔(由于每个分配组中初始分配的 inode )。

另一方面,动态 inode 分配造成大量问题,包括:

对于静态分配,文件系统的几何构造隐含描述了磁盘上 inode 的布局;对于动态分配,必需有单独的映射结构。

对 JFS 完整性而言,这些映射结构是至关重要的。由于复制这些结构的系统开销,JFS 决定接受丢失这些映射表的风险。但是,JFS 将复制 B+ 树结构,该结构允许 JFS 查找映射表。

通过只分配磁盘上 inode 连续大块的 inode 盘区,动态分配了 inode 。根据定义,一个 JFS inode 盘区包含 32 个 inode 。对于 512 字节的 inode 尺寸,因此磁盘上一个 inode 盘区的大小是 16KB。

当分配新的 inode 盘区时,并不初始化盘区。然而,要使 fsck 能够检查是否 inode 在使用中,JFS 需要 inode 的一些信息。一旦盘区中的 inode 标记成在使用中,就必须初始化它的文件集号、inode 号、inode 戳以及 inode 分配组块地址。因此,链接字段就足以确定 inode 当前是否正在使用。

注意,动态 inode 分配意味着在 inode 号与 inode 的磁盘地址之间没有直接关系。因此,JFS 必须有查找磁盘上 inode 的方法。inode 分配映射表提供了这一功能。

inode 生成号只是每当重用 inode 时值就增加的计数器。

存储每个 inode 生成计数器这一静态 inode 分配常用方法在动态 inode 分配中不起作用,因为当 inode 空闲时,其磁盘空间可能确实由不是 inode 的数据所重用,(换句话说,空间可能被收回,以存储普通文件数据)。因此,在 JFS 中,只有一个 inode 生成计数器,它在每一个 inode 分配时增加其值,即在重用 inode 时,相应的计数器增加其值,而不是每个 inode 有一个计数器。

B+ 树

这一节描述文件布局使用的 B+ 树数据结构。选择 B+ 树是为了提高读写盘区的性能,这是 JFS 必须进行的最普通操作。B+ 树为读取文件的特定盘区提供快速搜索。它还提供有效方法将盘区添加或插入文件中。较为少见的情形是:当删除文件时,JFS 需要遍历整个 B+ 树。为了保证 JFS 会删除 B+ 树使用的块以及文件数据,对于遍历 B+ 树效率也很高。

盘区分配描述符(xad 结构)描述盘区并且又添加了表示文件所需的两个字段:描述盘区表示的逻辑字节地址的偏移量和标志字段。盘区分配描述符结构在 jfs_xtree.h, struct xad 中定义。

xad 结构为:

struct xad {

unsigned flag:8;

unsigned rsvrd:16;

unsigned off1:8;

uint32 off2;

unsigned len:24;

unsigned addr1:8;

uint32 addr2;

} xad_t;

其中:

flag 是包含各种标志的 8 位字段。这些标志能够表示写入时复制、是否分配了盘区但没有记录它、压缩信息等等。

rsvrd 是保留供将来使用的 16 位字段。它总为零。

off1,off2 是 40 位字段,包含盘区中第一个块的逻辑偏移量。逻辑偏移量是以聚集块尺寸为单位表示;也就是说,要取得一个字节,偏移量必须乘以聚集块尺寸。

len 是 24 位字段,包含盘区的长度。长度以聚集块尺寸为单位表示。

addr1,addr2 是 40 位字段,包含盘区的地址。地址以聚集块尺寸为单位表示。

xad 结构描述了两个抽象范围:

磁盘上磁盘块的物理范围。它以聚集块号 xad_address 开始,并且延伸为 xad_length 聚集块。

文件内字节的逻辑范围。它以字节号 xad_offset * AGBS(聚集块尺寸)开始,并且延伸为 xad_length*AGBS 字节。

当然,物理范围和逻辑范围有相同长度的字节。请注意,xad_offset 以聚集块尺寸为单位存储(例如,在 xad_offset 中值 "3" 意味着 3 个聚集块,而不是 3 个字节)。它遵循文件内盘区总是以聚集块尺寸为边界。

JFS 中的所有索引对象(除目录外),有一个类属 B+ 树索引结构。索引的数据将取决于对象。B+ 树以由树描述的数据的 xad 偏移量为键。项按 xad 结构的偏移量排序。xad 结构是 B+ 树节点中的项。

图 3 显示了一个 xad 结构以及它是如何描述文件内逻辑字节范围和磁盘上字节范围本身(也就是说,对于聚集)的物理位置。

磁盘 inode 第二扇区底部包含数据描述符,它描述在 inode 的后半部分内存储的内容。对于足够小的文件,后半部分可能包含内嵌数据。如果文件数据不适合 inode 的内嵌数据空间,它将包含在盘区中,inode 将包含 B+ 树的根节点。头部指出在使用的 xad 个数,可用的 xad 个数。通常,inode 将包含 8 个 xad 结构 B+ 树的根。如果文件有 8 个或更少盘区,那么这 8 个 xad 结构也是 B+ 树的叶节点。它们将描述盘区。(参见图 4,例 1。)否则,inode 中的 8 个 xad 结构将指向 B+ 树的叶节点或内部节点。

一旦 inode 中的 8 个 xad 结构均已填充,为了有更多的 xad 结构,就会尝试使用 inode 的最后四分之一。如果 INLINEEA 位在 inode 的 di_mode 字段中设置,那么 inode 的最后四分之一可用。

一旦 inode 中所有可用的 xad 结构都被使用,就必须拆分 B+ 树。JFS 将把 4K 的磁盘空间分配给 B+ 树的叶节点。叶节点逻辑上是带头的 xad 项的数组。头部指向节点中第一个空闲的 xad 项,没有分配紧跟其后的所有 xad 项。8 个 xad 项从 inode 复制到叶节点,初始化头部以指向第 9 个项作为第一个空闲项。然后 JFS 将把 B+ 树的根更新为 inode 的第一个 xad 结构;该 xad 结构将指向最新分配的叶节点。这个新的 xad 结构的偏移量是叶节点中第一个项的偏移量。将更新 inode 中的头部以表示当前 B+ 树只使用 1 个 xad。还需要更新 inode 头部以表示当前 inode 包含 B+ 树的纯根。(参见图 4,例 2。)

当把新盘区添加到文件时,将以必需的次序,继续把它们添加到相同的叶节点。这将持续直到节点填满为止。一旦节点填满了,将为 B+ 树的另一个叶节点分配新的 4K 磁盘空间。将把该 inode 的第二个 xad 结构设置成指向新分配的节点。(参见 图 4,例 3。)

这将持续直到填满 inode 的所有 8 个 xad 结构为止,这时,将再次拆分 B+ 树。这种拆分将创建 B+ 树的内部 inode ,它们是纯粹用来记录树的搜索路径。JFS 将为 B+ 树的内部 inode 分配 4K 磁盘空间。内部节点看起来如同叶节点。从 inode 复制 8 个 xad 项到内部节点,初始化头部以指向第 9 个项作为第一个空闲项。然后,通过使 inode 的第一个 xad 结构指向新分配的内部节点,JFS 更新 B+ 树的根。将更新 inode 中的头部以表示当前 B+ 树只使用 1 个 xad。(参见图 4,例 4。)

文件 jfs_xtree.h 在 struct xtpage_t 中描述 B+ 树根的头部。文件 jfs_btree.h 是在 struct btpage_t 中的内部节点或叶节点的头部。

例子

下列例子进一步分析了盘区描述符和 xad 结构的用法:

连续分配的 1041377 字节文件。

相同的 1041377 字节文件,但在磁盘上拆分成三段。

1041377 字节的文件,但里面有一个"洞"(稀疏文件)。

连续分配的 16GB 文件。

在所有这些例子中,聚集块尺寸都是 1KB。

连续分配的 1041377 字节尺寸文件: 该文件需要 1017 个 1KB 聚集块,(在最后一个聚集块中,有 31 个字节丢失成为内部存储碎片)。要描述这个连续文件只需要一个 xad 结构:

flag 这里不讨论

offset 0 /* the beginning of the file */

[1] [2] [3] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有