我创建了一个稀疏文件filesystem.img
,用 格式化cryptsetup luksFormat
,并在其上创建了一个 btrfs 文件系统。在将文件添加到 btrfs 文件系统时,映像文件磁盘使用量会正常扩大。但是,删除其中的文件当然不会减少稀疏文件磁盘使用量,因此我需要一个手动执行此操作的解决方案。
不幸的fstrim
是不起作用,说the discard operation is not supported
。
我不能仅仅通过“dd”或“freezero”将零写入文件系统的文件,因为加密的零不是零,这会导致放大而不是缩小图像尺寸。
我可能可以将文件系统的大小调整为最小大小,然后将图像文件截断为文件系统大小 + luks 偏移量大小,但我发现 btrfs 非常不适合缩小,目前btrfs filesystem usage
报告可用空间约为 23G,已使用空间约为 81G,但我无法进一步减少,因此过度使用率约为 28%。
“btrfs balance” 可能会有帮助,但看起来它运行的时间甚至比将所有数据重新复制到新图像的时间更长。
最后一种当然是解决方案,但不是一个好的解决方案。并且并不总是能够创建具有所需空间的新磁盘映像。
我尝试通过创建相同的密码加密的零空图像来查找“解码的零”的样子,但每个 512 字节块(cryptosetup status 报告的大小)都不同。看起来 luks 不会使用相同的密钥加密每个块。
还有其他想法吗?
UPD。我还尝试用零文件填充 btrfs,找到它的偏移量:
# filefrag -b4K -ves zero
Filesystem type is: 9123683e
File size of zero is 34811904 (8499 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 3477: 17664.. 21141: 3478:
1: 3478.. 4732: 3399.. 4653: 1255: 21142:
2: 4733.. 5673: 11673.. 12613: 941: 4654:
3: 5674.. 6379: 16400.. 17105: 706: 12614:
4: 6380.. 6908: 4654.. 5182: 529: 17106:
5: 6909.. 7305: 12614.. 13010: 397: 5183:
6: 7306.. 7823: 15770.. 16287: 518: 13011:
7: 7824.. 8220: 17106.. 17502: 397: 16288:
8: 8221.. 8338: 5183.. 5300: 118: 17503:
9: 8339.. 8418: 13011.. 13090: 80: 5301:
10: 8419.. 8477: 17503.. 17561: 59: 13091:
11: 8478.. 8489: 13091.. 13102: 12: 17562:
12: 8490.. 8493: 13564.. 13567: 4: 13103:
13: 8494.. 8496: 3328.. 3330: 3: 13568:
14: 8497.. 8498: 13103.. 13104: 2: 3331: last,eof
将其保存到另一个文件系统文件中zero.frag
,并尝试用零填充图像文件的“物理”块:
# offset=4096
# cat zero.frag | tail -n +4 | head -n -1 | while read rec
do seek=${rec#*:*:}; seek=${seek%%.*}; seek=$((seek+offset))
count=${rec#*:*:*: }; count=${count%%:*}; count="${count#"${count%%[![:space:]]*}"}"
dd if=/dev/zero bs=4096 seek=$seek count=$count of=filesystem.img
done
但这破坏了文件系统。它仍然可以挂载,但现有文件不正确。此外,“filesystem.img”的磁盘使用量甚至比 btrfs 文件系统使用的空间还要少。所以仍然没有解决。
答案1
可以通过 3 个步骤手动完成:
partclone.btrfs -D
查找加密文件系统未使用的所有区域的位置和长度。我还没有找到一种简单的方法来获取这些信息。一种可能性是通过反转(+
标记已使用的块)输出中的块图来提取它。- 将 LUKS 数据偏移量添加到所有位置以获取 中的位置
filesystem.img
。如果您对虚拟磁盘进行了分区,则还需要添加分区偏移量。对于 LVM,您需要检查 LVM 元数据并将其映射应用于每个 LVM 区。 fallocate --punch-hole
按照步骤 2 中的确定--offset
方法运行--length
。对每个区域重复此操作。
不包括正在使用的全零块,因为通过 LUKS 层从稀疏块读取不会产生全零的块(或极不可能产生)。
请注意,cryptsetup luksDump
以 512 字节为单位报告有效载荷偏移。
警告:partclone 问题”域映射文件缺少 btrfs 所需的必要块“
资源:
- 将域映射文件转换
partclone
为fallocate --punch-hole
shell 脚本:https://gist.github.com/jowagner/4fa63bfedf0b3d9389550995505871c9 partclone -D
列出使用的块:https://github.com/Thomas-Tsai/partclone/issues/174
答案2
问题在于您使用原始磁盘映像文件来存储文件系统。这严重限制了您使该文件再次稀疏化的手段。
该工具virt-sparsify
可以使文件稀疏,但要求它未被使用,因此您必须在运行之前关闭使用该图像的虚拟机virt-sparsify
。
将来,如果您需要在线丢弃块,请使用支持此功能的备用存储,例如 qcow2 映像、ZFS、btrfs 或 LVM 精简配置块设备。