btrfs 巨大的元数据分配

btrfs 巨大的元数据分配

这个问题几乎与btrfs:已分配大量元数据,除了分区上数据大小的大小,以及新版本的linux内核4.4。

我正在尝试对 btrfs 分区进行完整映像备份。btrfs fil usage显示:

Overall:
    Device size:        4.50GiB
    Device allocated:   3.17GiB
    Device unallocated: 1.33GiB
    Device missing:       0.00B
    Used:               1.70GiB
    Free (estimated):   1.58GiB       (min: 936.52MiB)
    Data ratio:            1.00
    Metadata ratio:        2.00
    Global reserve:   512.00MiB       (used: 0.00B)

Data,single: Size:1.85GiB, Used:1.61GiB
    /dev/vda2      1.85GiB

Metadata,DUP: Size:640.00MiB, Used:49.38MiB
    /dev/vda2      1.25GiB

System,DUP: Size:32.00MiB, Used:16.00KiB
    /dev/vda2     64.00MiB

我发现元数据占用了 1.25GiB,而实际元数据大小只有不到 100MiB。如你所见,整个磁盘卷是 4.5GiB。这种空间浪费是不可接受的。

我尝试运行btrfs balance start -m并且btrfs balance start -musage=xx 从 0 变化到 50,但都无济于事。

有什么方法可以强制 btrfs 减少元数据的分配大小吗?或者,有什么方法可以将 btrfs 分区的大小调整到接近其实际占用的大小?

答案1

最后我发现了BTRFS 维基

元数据块组的典型大小为 256MiB(文件系统小于 50GiB)和 1GiB(大于 50GiB),数据块组为 1GiB。系统块组大小为几兆字节。

这就是元数据占用 512MiB 的原因(对于元数据的默认 RAID1,= 256MiB * 2)。但是,元数据的块大小似乎无法由用户指定。请参阅这封邮件

我不知道默认设置这么大的块大小(256MiB)的目的是什么。考虑到现在的存储容量很大,这可能是为了减少元数据碎片。无论如何,目前没有办法解决这个问题。所以当你需要额外的小分区时,就忘掉 btrfs 吧。

关于这个问题的一些额外故事:

很久以前,当我尝试对使用 btrfs 作为根分区的模板虚拟机进行磁盘转储时,这个问题就出现了。虽然未分配的部分在经过压缩后不会增加大小,但它确实会增加原始图像的大小,这有时会很不方便。同时,未使用的元数据空间在超小卷(小于 5GiB)上仍然是一种严重的浪费。

最后,我不得不使用 ext4 作为 rootfs,放弃 btrfs 提供的所有花哨功能(以及可能的风险)。希望有一天 btrfs 变得足够成熟,并公开对块大小的控制。然后我会尝试再次使用它构建转储。

PS:混合块对于小卷来说是一种不完美的方法,并且使用 btrfs 备份而不是进行完整转储。前者仍然存在浪费可用空间的问题,如果无法调整数据块大小,以及其他潜在问题。后者只需要额外的空间和从转储构建虚拟机的步骤,不要在没有 btrfs 支持的环境中运行,并且需要更多空间。

答案2

你把解决方案写在你的问题上,你对自己施加的限制相当低:

我尝试运行 btrfs balance start -m 和 btrfs balance start -musage=x 其中 x 从 0 到 50 变化,但它们都没有任何帮助。

50 表示您允许有 100-50=50% 未使用空间(浪费)的块。如果您输入 60,则表示您只允许最多有 40% 浪费空间的块,因此具有更多可用空间的块将被合并和释放。

只需使用一个更大的数字,该数字表示每个块必须使用多少百分比的块空间,如果一个块的使用率低于该百分比,它将与其他块合并为新的块,从而释放块。

只需尝试 55、60、65、70 ... 85、90、95、100,直到获得所需的结果。

或者如果您有足够的时间,直接使用 100,这样所有块都将被重新分配,并且它将使用尽可能少的块。

放入 100 并不意味着每个块(不是每个块小于 1)都将被 100% 填充,而是意味着除一个块之外的所有块都将被最大程度地填充,因此它将尽可能多地释放块,但代价是移动大量数据/元数据,这就是为什么所有人都建议尝试以较小的增量使用较大的值,以尽可能少地移动数据/元数据,直到用户对浪费的空间感到满意为止。

希望有一天,文档不仅对(专家)高级人员,而且对我这样的用户(新手)来说都会更加清晰......我花了一段时间才发现数据的块大小为 1GiB......我正在一个新 btrfs raid 1(两个设备)上写入一个小(<1KiB)文件,哇,可用空间少了 2GiB(每个设备一个)...而且我在想我所有的数据都丢失了,因为我写了更多的文件,而可用大小没有改变......它们都被写在一个完整的块上(实际上是两个块,每个设备一个)......直到我明白有一个以 1GiB 为单位的预分配。

如果一个块未填满,它仍然需要 1GiB 的空间;因此,如果您有两个块,填充率为 75%,那么您就浪费了两个 1GiB 块的 25%,也就是每个块 250MiB,所以总共是 500MiB,因为我谈论的是 RAID 1,所以在两个设备上也会发生同样的事情,所以总共浪费了 4GiB 中的 1GiB(2 个块 * 1GiB * 2 个设备),也就是浪费了 25% 的空间。

但是由于您输入的是 50 作为值,因此您接受的是 100%-50%=50% 的空间浪费。如果您输入的是 75,那么 100%-75%=25%,因此只有 25% 的空间浪费。Ando 等等。

如果您想最大限度地减少浪费的空间,请使用 99 或 100 等高值;但请注意,由于 CoW(写时复制),这意味着很多移动,如果使用 SSD/NVME/等则要格外小心,使用 USB 闪存/卡/等时也要格外小心。

希望这能帮助您和其他人理解。

注意:如果有人知道如何强制 Btrfs 在实际块填满之前不使用新块,那对我来说就太好了!我的意思是不要手动进行平衡

答案3

首先,BTRFS 每次都会分配一个块的元数据(和数据)。每个块为 1GB。即使分配了一块元数据,也并不意味着该块已充分利用。请记住,BTRFS 还会在元数据中存储较小的文件,这可能会导致您的元数据使用率“过高”。

默认情况下,BTRFS 还会复制元数据,以增加文件系统在发生损坏时恢复的机会。数据不会被复制。

您可以通过将元数据重新平衡到单个配置文件来减少元数据的使用,但代价是恢复的可能性,这可能是您所希望的,具体取决于您的用例。您可以这样做:

btrfs balance start -dconvert=single /mountpoint

您还可以查找混合块组,这将使 BTRFS 不分配单独的元数据块,而是将数据和元数据存储在相同的块中。

另外值得一提的是,当您使用使用情况过滤器运行平衡时,您所说的是仅平衡利用率小于 X 的块。

相关内容