这个问题几乎与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=x
x 从 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 的块。