布局

标准块组的布局大致如下(以下每个字段将在单独的章节中讨论)

组 0 填充

ext4 超级块

组描述符

保留的 GDT 块

数据块位图

inode 位图

inode 表

数据块

1024 字节

1 块

多块

多块

1 块

1 块

多块

更多块

对于块组 0 的特殊情况,前 1024 字节未使用,以便安装 x86 引导扇区和其他特殊情况。超级块将从偏移 1024 字节处开始,无论这是哪个块(通常是 0)。但是,如果由于某种原因块大小 = 1024,则块 0 被标记为已使用,超级块位于块 1。对于所有其他块组,没有填充。

ext4 驱动程序主要处理块组 0 中的超级块和组描述符。超级块和组描述符的冗余副本写入磁盘上的某些块组,以防磁盘开头被损坏,尽管并非所有块组都必然包含冗余副本(有关详细信息,请参阅下一段)。如果该组没有冗余副本,则块组以数据块位图开始。另请注意,当文件系统首次格式化时,mkfs 会在块组描述符之后和块位图开始之前分配“保留 GDT 块”空间,以便将来扩展文件系统。默认情况下,文件系统允许比原始文件系统大小增加 1024 倍。

inode 表的位置由 grp.bg_inode_table_* 给出。它是一个连续的块范围,其大小足以容纳 sb.s_inodes_per_group * sb.s_inode_size 字节。

至于块组中项目的顺序,通常确定超级块和组描述符表(如果存在)将位于块组的开头。位图和 inode 表可以位于任何位置,并且位图很可能位于 inode 表之后,或者两者位于不同的组中 (flex_bg)。剩余空间用于文件数据块、间接块映射、范围树块和扩展属性。

弹性块组

从 ext4 开始,有一个名为弹性块组 (flex_bg) 的新功能。在 flex_bg 中,几个块组作为一个逻辑块组捆绑在一起;flex_bg 中第一个块组中的位图空间和 inode 表空间被扩展,以包括 flex_bg 中所有其他块组的位图和 inode 表。例如,如果 flex_bg 大小为 4,则组 0 将(按顺序)包含超级块、组描述符、组 0-3 的数据块位图、组 0-3 的 inode 位图、组 0-3 的 inode 表,组 0 中的剩余空间用于文件数据。其效果是将块组元数据紧密地分组在一起以便更快加载,并使大文件在磁盘上连续。即使启用了 flex_bg,超级块和组描述符的备份副本也始终位于块组的开头。构成 flex_bg 的块组数量由 2 ^ sb.s_log_groups_per_flex 给出。

元块组

在没有 META_BG 选项的情况下,出于安全考虑,所有块组描述符副本都保存在第一个块组中。给定默认的 128MiB(2^27 字节)块组大小和 64 字节的组描述符,ext4 最多可以有 2^27/64 = 2^21 个块组。这将整个文件系统大小限制为 2^21 * 2^27 = 2^48 字节或 256TiB。

解决此问题的方法是使用元块组功能 (META_BG),该功能已在 ext3 的所有 2.6 版本中提供。借助 META_BG 功能,ext4 文件系统被划分为许多元块组。每个元块组都是一组块组,其组描述符结构可以存储在单个磁盘块中。对于块大小为 4 KB 的 ext4 文件系统,单个元块组分区包括 64 个块组,即 8 GiB 的磁盘空间。元块组功能将组描述符的位置从整个文件系统拥挤的第一个块组移动到每个元块组本身的第一个组中。备份位于每个元块组的第二个和最后一个组中。这将 2^21 的最大块组限制增加到硬限制 2^32,从而支持 512PiB 文件系统。

文件系统格式的更改取代了当前超级块后跟可变长度块组描述符集的方案。相反,超级块和单个块组描述符块放置在元块组中的第一个、第二个和最后一个块组的开头。元块组是可以通过单个块组描述符块描述的块组集合。由于块组描述符结构的大小为 64 字节,因此对于块大小为 1KB 的文件系统,元块组包含 16 个块组;对于块大小为 4KB 的文件系统,元块组包含 64 个块组。文件系统可以使用这种新的块组描述符布局创建,或者现有文件系统可以在线调整大小,并且超级块中的 s_first_meta_bg 字段将指示使用这种新布局的第一个块组。

请参阅有关块和 inode 位图部分中关于 BLOCK_UNINIT 的重要说明。

惰性块组初始化

ext4 的一个新功能是三个块组描述符标志,它们使 mkfs 能够跳过初始化块组元数据的其他部分。具体来说,INODE_UNINIT 和 BLOCK_UNINIT 标志表示该组的 inode 和块位图可以计算,因此磁盘上的位图块未初始化。这通常是空块组或仅包含固定位置块组元数据的块组的情况。INODE_ZEROED 标志表示 inode 表已初始化;mkfs 将取消设置此标志,并依靠内核在后台初始化 inode 表。

通过不向位图和 inode 表写入零,mkfs 时间大大减少。请注意,功能标志是 RO_COMPAT_GDT_CSUM,但 dumpe2fs 输出将其打印为“uninit_bg”。它们是同一件事。