我正在尝试分析 BTRFS 写入过程的行为。我需要创建一个简单的测试程序,它产生(显然在用户级别)与 BTRFS 模块在物理硬盘上生成的 blob 相同的压缩 blob。
在启用压缩的 BTRFS 文件系统下写入文件的具体步骤是什么?文件是否拆分为文件页/范围?文件页大小如何确定?压缩过程是确定性的吗?文件页大小如何确定?尽管有大量可用空间,但某些文件页不是 128KiB 大(最大容量)。怎么来的?压缩的确切规则是什么?尽管压缩率很高,但某些文件页并未被压缩。怎么来的?
在阅读了一些文档和源代码(linux/fs/btrfs/zlib.c & linux/fs/btrfs/inode.c)并使用小文件(小于 10KiB)测试 FS 后,我的发现(以及更多问题):(纠正我)
*较小的文件被分成 4096 字节的页面以便进一步压缩。压缩的 blob 是连续的。使用 zlib,较小的文件仅保存为 1 blob(以 0x785E 开头)。较大的文件保存为单独的非连续 blob。使用 zlib 将更大的文件保存为多个 0x785E blob。在压缩之前对这些大文件进行碎片化的步骤是什么?片段大小是如何确定的?
*如果文件小于扇区大小(512 字节),则文件保存为原始文件。正确的?
*如果压缩尝试未能节省至少 1x PAGE_SIZE 的空间(即至少 4096 字节),则文件将保存为原始文件并标记为不可压缩。正确的?
编写过程的伪代码会很好。请原谅我对 BTRFS 规范的无知。预先感谢您的帮助。
更新:在做进一步的测试后,我已经可以回答我自己的一些问题了。
更新:我发现了另一种极端情况,其中文件页的大小不是 128KiB。我仍然需要知道压缩过程的确切规则。
更新:我改变了我的问题。回答我之前的问题:
(a) 是的,这些文件通常被分成 128-KiB 大的页面;有些页面较小。一些小文件(我仍然不知道它们的条件——有多小?)被压缩或原始保存到内联范围中。
(b) (我仍然不知道这个问题的答案)通常如果有很多可用空间,文件页的大小为 128-KiB。在某些情况下(非连续可用空间和其他未知条件尚未确定),某些文件页设置为 0x1000 字节(4096 字节)的倍数。
(c) 压缩函数是确定性的。但是,由于不同操作环境中的相同文件的处理方式不同(文件页大小不同,压缩标记不同),因此不同磁盘上相同文件的压缩 blob 在磁盘上彼此不同。如果文件在完全相同的环境中处理,则其压缩的 blob 在磁盘上将是相同的。
主要规则:
该文件将被分成多个 128KiB 页面。(至少对于 zlib)每页要分成 4096 字节的步(每页最多 128 步)。压缩启发式检查(以确保压缩输出小于原始输入)从第 3 步开始,直到页面结束 - 对于前 2 步,不进行任何检查。从压缩循环的第 3 步开始,如果压缩后的输出大于原始输入,则取消当前页面的压缩过程,并将当前页面保存为原始 blob。
成功后,页面将保存为压缩 blob - 在默认 zlib 设置下,blob 以 0x785E 开头。压缩的 blob 在末尾用 0x00 填充。
附带规则:
如果文件小于 512 字节并且存储到内联扩展区中,则文件将被保存为原始文件。
如果压缩文件的大小 + 扇区大小(默认为 512 字节)小于原始文件的大小,则接受压缩输出,否则丢弃压缩输出并将文件标记为不可压缩。
如果文件的可用空间非常稀缺,则将文件划分为不相等的页面 - 某些页面的大小不会为 128KiB。