BlobFS

BlobFS 是一个内容可寻址文件系统,针对单次写入、 经常读取的文件,例如二进制文件和库。在 Fuchsia 上,BlobFS 是 存储系统

装载后,BlobFS 会显示包含所有文件的单个逻辑目录 (也称为 blob):

blob/
 ├── 00aeb9b5652a4adbf630d04a6ca22668f9c8469746f3f175687b3c0ff6699a49
 ├── 01289d3e1d2cdbc7d1b4977210877c5bbdffdbad463d992badc149152962a205
 ├── 018951bcf92091fd5d294cbd1f3a48d6ca59be7759587f28077b2eb754b437c0
 └── 01bad8536a7aee498ffd323f53e06232b8a81edd507ac2a95bd0e819c4983138

BlobFS 中的文件包括:

  • 不可变:blob 一经创建便无法修改(移除除外)。
  • Content-Addressable:Blob 名称确定性地派生自其 内容。
  • 已验证:使用加密校验和来确保 blob 的完整性 数据。

blob 的这些特性使得 BlobfS 成为 Fuchsia 安全的关键组件 确保软件包的运行状态可以先对其进行验证, 。

BlobFS 的设计和实现

磁盘格式

BlobFS 将每个 blob 存储在一个非相邻范围(一个连续的) 数据块范围)。每个 blob 都有一个关联的 Inode,用于描述 块的数据始于磁盘以及有关 blob 的其他元数据。

BlobFS 将磁盘(或其分区)分为五个区块:

  • 存储文件系统级元数据的 Superblock
  • 块映射,一种用于跟踪可用数据和已分配数据的位图 方块、
  • 节点映射:Inode 的平面数组(对 blob 数据所在位置的引用 或 ExtentContainers(对包含 blob 的某些数据)。
  • 日志,这是文件系统操作日志,用于确保文件系统 完整性,即使设备在操作期间重新启动或断电; 和
  • 数据块,其中 blob 内容及其验证元数据 存储在一系列范围中

BlobFS 磁盘布局

图 1:BlobFS 磁盘布局

超级区块

超块是 BlobFS 格式的分区中的第一个块。它描述了 文件系统中其他块的位置和大小,以及其他数据块, 或文件系统级元数据

装载 BlobFS 格式的文件系统时,此块会映射到内存 并解析以确定文件系统的其余部分的位置。该代码块是 会在创建新 blob 时修改,并且(适用于 FVM 管理的 BlobFS 实例) 。

BlobFS 超级块

图 2:BlobFS 超级块

当 BlobFS 由 FVM 管理时,超块包含一些额外的元数据 描述包含 BlobFS 文件系统的 FVM 切片。这些字段 对于非 FVM、固定大小的 BlobFS 图片,将忽略(上图中的黄色部分)。

屏蔽地图

块映射是一个简单的位图,用于将每个数据块标记为已分配或 错误。此映射在块分配期间用于查找 用于存储 blob 内容的块(称为范围)。

块映射示例

图 3:包含多个不同大小的自由区域的示例块映射。

装载 BlobFS 映像时,块映射会映射到内存中, 被块分配器读取每当有人执行上述操作时, 块被分配(在 blob 创建期间)或解除分配(在 blob 删除期间)。

节点映射

节点映射是文件系统上所有节点的数组,有两种类型 变体:

  • Inode:描述文件系统上的单个 Blob,或
  • ExtentContainers,指向包含 Blob 的 数据。

这两种类型的节点一起存储在单个平面数组中。每个节点都有一个 公共标头,用于说明节点的类型以及节点是否 已分配。这两种节点类型的大小相同,因此没有内部 数组的碎片化。

Inode

文件系统中的每个 Blob 都有一个对应的 Inode,该 Inode 描述了 blob 的数据开始以及有关 blob 的一些其他元数据。

BlobFS Inode 的布局

图 4:BlobFS Inode 的布局。

对于小型 blob,Inode 可能是描述 blob 在磁盘上在此示例中,extent_count 为 1,而 next_node 不得为 inline_extent 描述 blob 的单个范围。

较大的 blob 可能会占据多个范围,尤其是在碎片化的 BlobFS 映像。在这种情况下,blob 的第一个范围存储在 inline_extent,而所有后续范围都存储在 ExtentContainers 从 next_node. 开始

范围的格式

图 5:范围的格式(占用 64 位)。此格式同时用于 Inodes 和 ExtentContainers。

请注意,这种范围的表示意味着,一个范围最多只能有 其中 2**16 个块(范围大小的最大值)。

ExtentContainers

ExtentContainer 保存对多个(最多 6 个)范围的引用,这些范围用于存储 Blob 的部分内容。

ExtentContainer 中的范围在逻辑上是连续的(即 存储在 extents[0] 中的 blob 的可寻址块在 extents[1] 之前,并且 。如果设置了 next_node,则 ExtentContainer 必须已满。

BlobFS ExtentContainer 的布局

图 6:BlobFS ExtentContainer 的布局。

节点链接列表的属性

blob 的范围保存在单个 Inode(该节点用于存放 和零个或多个 ExtentContainer(每个容器最多可容纳 6 个) 范围)。

此关联列表包含以下属性。违反这些属性 会导致 blobfs 将 blob 视为已损坏。

  • 范围在逻辑上是连续的: <ph type="x-smartling-placeholder">
      </ph>
    • 如果列表中的节点 A 在节点 B 之前,则节点 A 中的所有范围都有 更低的逻辑偏移量
    • 在给定的 ExtentContainer 中,对于范围 x 和 y,如果 x <y 键,然后按 范围 x 与 blob 内容的逻辑偏移量小于范围 y。
  • 在关联新节点之前,节点会被打包。也就是说,如果节点具有 非 null next_node,则范围必须全部(*对于 Inode 的范围) 而对于 ExtentContainers,则为 6 个范围)。
  • 链接列表中的范围总数必须等于 Inode 的 extent_count
  • 链接列表中所有范围的大小总和必须等于 Inode 的 block_count
  • 列表的末尾根据 Inode 中的 extent_count 确定 获得满意的体验不应使用最终节点中的 next_node
Node 布局示例

本部分包含一些示例,说明了 blob 的节点 格式。

示例:单范围 blob

示例:单范围 blob

图 7:存储在单个范围内的 blob 的节点布局

示例:多个范围的 blob

示例:多个范围的 blob

图 8:存储在多个区段中的 blob 的节点布局。请注意,blob 的 个范围可能分散在整个磁盘中。

Blob 分片

新创建的 BlobFS 映像的所有数据块都免费。范围 并且 blob 往往存储在单个 大范围(或少数几个大范围内)。

随着时间的推移,随着 blob 的分配和取消分配,块映射将变为 细分成许多较小的范围。新创建的 Blob 必须是 存储在多个较小的范围内

碎片化的块映射

图 9:碎片化的块映射。虽然有很多免费块, 大范围可用。

不合理,原因如下:

  • 读取速度较慢:读取碎片化的 blob 需要在 节点映射。这会同时影响顺序读取和随机访问读取
  • 减慢创建和删除速度:创建 blob 需要免费查找 范围;如果必须找到许多小范围,则所需的时间会更长。 同样,删除碎片化的 blob 需要追逐和释放许多 范围。
  • 元数据开销:存储碎片化的 blob 需要更多节点。那里 是 Node Map 中有限数量的节点,可能会耗尽, 来防止创建 Blob。

目前,BlobFS 不执行碎片整理。

日志

TODO

数据块

最后,blob 的实际内容必须存储在某个地方。通过 BlobFS 映像中剩余的存储块均指定用于此用途。

系统会为每个 blob 分配足够的范围,以包含其所有数据,以及一个 为存储 blob 的验证元数据而预留的数据块数。 此元数据始终存储在 blob 的前块中。元数据现为 已填充,以便实际数据始终从块对齐的地址开始。

这些验证元数据称为 Merkle 树,是一种数据结构, 使用加密哈希值来保证 Blob 内容的完整性。

Merkle 树

blob 的 Merkle 树的构建方式如下(有关详情,请参阅 Fuchsia Merkle Roots):

  • 每个叶节点都是单个分块数据的 sha256 哈希值。
  • 每个非叶节点都是一个组合其子节点哈希的 sha256 哈希。
  • 树在具有单个 sha256 哈希的级别终止。

最顶层节点的哈希值称为 blob 的 Merkle Root。 此值用作 blob 的名称。

Merkle Tree 的简化示例

图 10:简化的 Merkle 树示例。请注意,在实际使用中, 信息(例如块偏移量和 并且每个非叶节点要更宽(特别是 非叶节点最多可包含 8192 / 32 == 256 个子节点)。

BlobFS 实现

与其他 Fuchsia 文件系统一样,BlobFS 是作为用户空间进程实现的 通过 FIDL 接口为客户端提供服务。