inode.i_block 的内容¶
根据 inode 描述的文件类型,inode.i_block
中 60 字节的存储空间可以有不同的用途。通常,常规文件和目录会将其用于文件块索引信息,而特殊文件会将其用于特殊目的。
符号链接¶
如果目标字符串长度小于 60 字节,符号链接的目标将存储在此字段中。否则,将使用 extent 或块映射来分配数据块以存储链接目标。
直接/间接块寻址¶
在 ext2/3 中,文件块号通过(最多)三级一对一的块映射映射到逻辑块号。为了找到存储特定文件块的逻辑块,代码会遍历这个日益复杂的结构。请注意,既没有魔数也没有校验和来提供任何程度的信心,以确保该块不是一堆垃圾。
i.i_block 偏移 |
指向位置 |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 到 11 |
直接映射到文件块 0 到 11。 |
||||||||||||
12 |
间接块:(文件块 12 到 (
|
||||||||||||
13 |
双间接块:(文件块
|
||||||||||||
14 |
三间接块:(文件块 (
|
请注意,使用这种块映射方案,即使对于大型连续文件,也需要填充大量的映射数据!这种低效率导致了下面将讨论的 extent 映射方案的创建。
另请注意,使用此映射方案的文件不能大于 2^32 个块。
Extent 树¶
在 ext4 中,文件到逻辑块的映射已被 extent 树取代。在旧方案中,分配 1,000 个连续块需要一个间接块来映射所有 1,000 个条目;使用 extent,映射被简化为单个 struct ext4_extent
,其中 ee_len = 1000
。如果启用了 flex_bg,则可以使用单个 extent 分配非常大的文件,大大减少了元数据块的使用,并提高了磁盘效率。必须为 inode 设置 extents 标志 (0x80000) 才能使用此功能。
Extent 被组织成一棵树。树的每个节点都以 struct ext4_extent_header
开头。如果节点是内部节点 (eh.eh_depth
> 0),则标题后面跟着 eh.eh_entries
个 struct ext4_extent_idx
实例;这些索引条目中的每一个都指向包含 extent 树中更多节点的块。如果节点是叶节点 (eh.eh_depth == 0
),则标题后面跟着 eh.eh_entries
个 struct ext4_extent
实例;这些实例指向文件的数据块。Extent 树的根节点存储在 inode.i_block
中,这使得可以记录前四个 extent 而无需使用额外的元数据块。
extent 树的头部记录在 struct ext4_extent_header
中,其长度为 12 字节
偏移量 |
大小 |
名称 |
描述 |
---|---|---|---|
0x0 |
__le16 |
eh_magic |
魔数,0xF30A。 |
0x2 |
__le16 |
eh_entries |
头部后面有效条目的数量。 |
0x4 |
__le16 |
eh_max |
头部后面可能跟随的最大条目数。 |
0x6 |
__le16 |
eh_depth |
此 extent 节点在 extent 树中的深度。0 = 此 extent 节点指向数据块;否则,此 extent 节点指向其他 extent 节点。extent 树最多可以有 5 层深:逻辑块号最大为 |
0x8 |
__le32 |
eh_generation |
树的代。(由 Lustre 使用,但非标准 ext4)。 |
extent 树的内部节点,也称为索引节点,被记录为 struct ext4_extent_idx
,长度为 12 字节
偏移量 |
大小 |
名称 |
描述 |
---|---|---|---|
0x0 |
__le32 |
ei_block |
此索引节点涵盖从“block”开始的文件块。 |
0x4 |
__le32 |
ei_leaf_lo |
树中下一层 extent 节点块号的低 32 位。所指向的树节点可以是另一个内部节点或叶节点(如下所述)。 |
0x8 |
__le16 |
ei_leaf_hi |
前一个字段的高 16 位。 |
0xA |
__u16 |
ei_unused |
extent 树的叶节点被记录为 struct ext4_extent
,长度也为 12 字节
偏移量 |
大小 |
名称 |
描述 |
---|---|---|---|
0x0 |
__le32 |
ee_block |
此 extent 涵盖的第一个文件块号。 |
0x4 |
__le16 |
ee_len |
extent 涵盖的块数。如果此字段的值 <= 32768,则 extent 已初始化。如果此字段的值 > 32768,则 extent 未初始化,实际 extent 长度为 |
0x6 |
__le16 |
ee_start_hi |
此 extent 指向的块号的高 16 位。 |
0x8 |
__le32 |
ee_start_lo |
此 extent 指向的块号的低 32 位。 |
在引入元数据校验和之前,extent 头部 + extent 条目总是在每个 extent 树数据块的末尾留下至少 4 字节的未分配空间(因为 (2^x % 12) >= 4)。因此,32 位校验和被插入到这个空间中。inode 中的 4 个 extent 不需要校验和,因为 inode 已经过校验。校验和是针对文件系统 UUID、inode 号、inode 代以及直到(但不包括)校验和本身的整个 extent 块计算的。
struct ext4_extent_tail
长度为 4 字节
偏移量 |
大小 |
名称 |
描述 |
---|---|---|---|
0x0 |
__le32 |
eb_checksum |
extent 块的校验和,crc32c(uuid+inum+igeneration+extentblock) |
内联数据¶
如果文件系统启用了内联数据功能,并且为 inode 设置了该标志,则文件数据的前 60 字节可能会存储在此处。