6 个版本 (破坏性更新)

0.11.0 2024年7月30日
0.10.0 2024年7月3日
0.9.0 2024年5月22日
0.8.0 2024年5月1日
0.6.0 2024年3月29日

535文件系统

Download history 148/week @ 2024-04-28 5/week @ 2024-05-05 5/week @ 2024-05-12 231/week @ 2024-05-19 11/week @ 2024-05-26 12/week @ 2024-06-02 13/week @ 2024-06-09 14/week @ 2024-06-16 7/week @ 2024-06-23 159/week @ 2024-06-30 46/week @ 2024-07-07 24/week @ 2024-07-14 1/week @ 2024-07-21 226/week @ 2024-07-28 15/week @ 2024-08-04 23/week @ 2024-08-11

每月下载 266
8 个包中使用 (通过 maelstrom-worker)

MIT/Apache 协议

675KB
17K SLoC

Maelstrom FUSE

此库包含一个用于 Maelstrom 项目的 FUSE 文件系统实现,名为 LayerFS。

有关更多信息,请参阅 GitHub 上的 Maelstrom 项目


lib.rs:

此包包含一个名为 LayerFS 的 Linux FUSE 文件系统实现。

简介

该文件系统基于“层”构建,可以相互堆叠。每一层代表一个完整的文件系统,当堆叠在一起时,文件系统会被合并。当文件系统合并时,位于“顶部”的文件系统会被优先考虑。这实现了类似于 overlay-fs 的效果。

磁盘布局

层存储在磁盘上作为一个文件的目录。每个目录包含以下文件

  • super.bin 包含有关层的所有信息,包括其堆叠在上面的任何层
  • file_table.bin 包含层中所有文件的列表
  • attributes_table.bin 包含层中所有文件的特征
  • <<offset>>.dir_data.bin 包含在文件表中找到的 <offset> 目录的内容

请注意,上述所有项目符号都没有提到包含文件数据。大多数文件数据实际上是从层外部的文件中读取的。这就是在LayerFs::from_path中使用的cache_dir所用于的。然而,如果一个文件包含少量数据,它实际上可以以“内联数据”的形式存储在属性中,以避免从另一个文件读取的开销。

堆叠

当一个层堆叠在其他层之上时,该层的目录条目可能指向较低层的目录或文件。这是因为FileId包含一个LayerId。这允许我们创建上述类似于overlay-fs的功能。

当一个上层包含在较低层也存在的文件时,较低层的文件会被上层文件遮挡。当一个上层包含在较低层也存在的目录时,目录内容会被合并。

+------------------------+             +-----------+
| /   layer_id 2         |  built from | /         |
| `-- a.txt => (2, 10)   | <========== | `-- a.txt |
| `-- b.txt => (2, 3)    |             +-----------+
| `-- c.txt => (1, 3)    |
| `-- d/ => (0, 3)       |
+------------------------+             +-----------+
| /   layer_id 1         |  built from | /         |
| `-- a.txt => (1, 10)   | <========== | `-- a.txt |
| `-- c.txt => (1, 3)    |             | `-- c.txt |
| `-- d/ => (0, 3)       |             +-----------+
+------------------------+
| /   layer_id 0         |
| `-- d/ => (0, 3)       |
|     `-- e.txt => (0, 4)|
+------------------------+

图1. 三层堆叠

在图1中,我们展示了每个目录条目FileId,以说明堆叠功能如何工作。以下是各层的描述

  • 层0有一个目录/d和一个文件/d/e.txt。由于这是一个底层,所有目录条目都有LayerId 0
  • 层1有两个文件/a.txt/c.txt。它还有一个来自层0的/d目录条目。由于这个层没有自己的/d条目,所以它是合并进来的。
  • 层2有文件/a.txt/b.txt/c.txt和目录/d。它继承了/b.txt/c.txt/d的条目。这是因为它们所有的FileId都指向层1或0。/a.txtLayerId 2,这意味着这个文件正在遮盖来自层1的/a.txt。这意味着层1中的/a.txt现在无法访问。

构建层

从概念上讲,有两种不同类型的层:“底层”和“上层”。上层是堆叠在其他层之上的层。底层是那些没有被堆叠在其他任何层之上的层,因此是自给自足的。上层需要它们所堆叠的层存在才能使用。上层是通过在某个层之上堆叠一个底层来创建的。

+----------------+
| 2 upper layer  | <-------+
+----------------+         |
+----------------+         | UpperLayerBuilder::fill_from_bottom_layer
| 1 upper layer  |         |
+----------------+         |
+----------------+  +---------------+
| 0 bottom layer |  |  bottom layer |
+----------------+  +---------------+

图2. 正在创建一个新的id为2的上层,堆叠在其他两个层之上。

在创建底层时,必须使用BottomLayerBuilder。它可以使用清单或tar文件作为输入来创建底层。

在创建上层时,必须使用UpperLayerBuilder。要在上层中堆叠的层的路径作为输入提供给UpperLayerBuilder::new。作为创建上层输入的底层层传递给UpperLayerBuilder::fill_from_bottom_layer

创建上层时,它们堆叠在上面的层不会被修改。这意味着层可以在多个堆叠中重复使用。这也是层编号从下往上进行的原因。

文件系统服务

通过FUSE提供文件系统服务。首先,应将想要服务的层堆叠的顶层的路径传递给LayerFs::from_path。然后调用LayerFs::mountLayerFs::run_fuse

依赖项

~18–31MB
~465K SLoC