我有一个系统映像稀疏文件,其实际大小只有几 MB,但“表观大小”约为 1GB。我正在尝试将其有效地写入块设备(没有漏洞)。以下是我尝试过的一些无效的解决方案:
dd if=sparse_file of=/dev/some_dev
处理整个文件,包括漏洞,所以最后我得到类似的东西1007869952 bytes (1,0 GB) copied, 22,0301 s, 45,7 MB/s
cp --sparse=always sparse_file /dev/some_dev
似乎也不起作用,因为几个 MB 需要很长时间(~13 秒)ddrescue --sparse --force sparse_file /dev/some_dev
失败并显示一条消息ddrescue: Only regular files can be sparse.
(注意:它的工作方向与所涵盖的相反这里)。
还有另外 2 种方法这里但我只想使用 Linux 发行版中的标准工具。
那么有没有办法将稀疏文件写入块图像而跳过漏洞呢?
答案1
这个工具用C写的可能对你有帮助。它不是标准工具,但非常简单且易于编译。
你是对的,cp
不支持稀疏输出到块设备(在手册页中确认)。
答案2
我遇到了与此线程相关的问题:我创建了一个具有完整性的 LUKS 加密块设备。我想擦除每个扇区(即逻辑块),以便在从扇区读取数据之前检查扇区的完整性。在“luksFormat”时,cryptsetup(8) 默认会擦除所有扇区。如果我覆盖一个扇区,该扇区的完整性位也会被覆盖,所以我不需要关心它之前的完整性检查是否。但是,如果部分写入导致内核读取该扇区,并且可能与页大小内的相邻扇区一起读取,并且无法检查相关完整性,则写入将失败。不幸的是,mke2fs 写入了部分扇区。所以我无法在未擦除的此类设备上 mke2fs。所以我写了这个“sparseblk”实用程序。我可以在纯文件上创建一个 fs 映像,然后将纯文件写入设备。这个“sparseblk”实用程序通过 lseek(fd, offset, SEEK_DATA) 跳过其输入中的漏洞,并在写入时将数据填充到扇区边界。挂载文件系统后,内核会写入整个扇区。
假设场景:https://gitlab.com/cryptsetup/cryptsetup/issues/335#note_270050959
truncate -s 1G /tmp/1.img /tmp/2.img
truncate -s 980M /tmp/1.img /tmp/2.img
mke2fs /tmp/2.img
cryptsetup luksFormat \
--key-file /etc/motd \
--sector-size $(getconf PAGESIZE) \
--cipher chacha20-plain \
--integrity poly1305 \
--integrity-no-wipe \
/tmp/1.img
cryptsetup open --key-file /etc/motd /tmp/1.img dm-0
argv[0] < /tmp/2.img > /dev/mapper/dm-0
mount /dev/mapper/dm-0 /mnt/1
我还没有使用 e2fsck 和 resize2fs 等对其进行测试。
不管怎样,如果我认真对待安全问题,我会擦除整个设备。
您可以将此“sparseblk”实用程序用于其他目的。如果将此“sparseblk”实用程序用于其他目的,您可以忽略“逻辑块大小不是页面大小的倍数”警告。
posix 正在采用 SEEK_DATA SEEK_HOLE:http://austingroupbugs.net/view.php?id=415
“稀疏块”:https://gist.github.com/insulsa/18b7d31bd82ddade14db07f413c0b2d2
答案3
我只想使用 Linux 发行版中的标准工具。
例如,默认情况下会安装什么?
根据您的想法,有两个可能的答案:
dd 支持
conv=sparse
作为标志。只要您知道目标设备已全部清零,只需dd if=sparse_file conv=sparse of=/path/to/device
qemu-img 可以从大多数标准发行版存储库安装,并且它可以理解稀疏格式和书写。如果目标块设备支持 TRIM,它将稀疏写入目标,并且从版本 4 开始(我认为是?),您可以通过参数强制它稀疏写入
--target-is-zero
:
qemu-img convert -O raw sparse_file /path/to/device
或强迫它
qemu-img convert -O raw --target-is-zero sparse_file /path/to/device