Iva*_*van 10 sparse-files files
在 Linux 上,给定一个稀疏文件,如何使其成为非稀疏文件?
可以用 复制cp --sparse=never ...
,但是如果文件是10G,洞是2G(即分配的空间是8G),如何让文件系统分配剩余的2G而不将原来的8G复制到新文件中?
fro*_*utz 13
从表面上看,它很简单dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Run Code Online (Sandbox Code Playgroud)
这会读取整个文件,并将整个内容写回其中。
为了只写孔本身,您首先必须确定这些孔的位置。您可以使用filefrag
或来做到这一点hdparm
:
文件片段:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
Run Code Online (Sandbox Code Playgroud)
hdparm:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
Run Code Online (Sandbox Code Playgroud)
正如您所说,此示例文件的10G
大小带有一个2G
孔。它有两个范围,第一个覆盖0-1048575
,第二个1572864-2621439
,这意味着孔是1048576-1572864
(以 4k 大小的块为单位,如 所示filefrag
)。显示的信息hdparm
是相同的,只是显示不同(第一个范围涵盖8388608
从 0 开始的 512 字节扇区,因此它是0-4294967295
字节,因此空洞4294967296-6442450944
以字节为单位。
请注意,如果有任何碎片,您可能会看到更多的范围。不幸的是,这两个命令都没有直接显示孔,我不知道有哪个命令会这样做,因此您必须从显示的逻辑偏移量中推断出它。
现在,填充该1048576-1572864
具有空穴dd
如上所示,可以通过添加适当的(相同的)来完成seek
/skip
值和count
。请注意,bs=
已调整为使用上面使用的4k
扇区filefrag
。(对于bs=1M
,您必须调整搜索/跳过/计数值以反映1M
大小的块)。
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Run Code Online (Sandbox Code Playgroud)
虽然您可以填充空洞/dev/zero
而不是读取文件本身的空洞(这也只会产生零),但sparsefile
无论如何读取更安全,这样您就不会在偏移错误的情况下损坏数据。
在较新版本的 中GNU dd
,您可能会坚持使用更大的块大小并以字节为单位指定所有值:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
Run Code Online (Sandbox Code Playgroud)
filefrag
运行后:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
Run Code Online (Sandbox Code Playgroud)
由于碎片化,还是两个extent。但是,逻辑偏移量显示,这次没有空洞,因此文件不再稀疏。
自然,这个dd
解决方案是非常手动的方法。如果您经常需要它,编写一个小程序来填补这些空白会很容易。如果它已经作为标准工具存在,我还没有听说过。
毕竟有一个工具,fallocate
似乎可以工作,经过时尚:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
Run Code Online (Sandbox Code Playgroud)
然而,最后在 XFS 的情况下,虽然它确实为这个文件分配了物理区域,但实际上并没有将其归零。filefrag
显示已分配但未写入的范围。
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Run Code Online (Sandbox Code Playgroud)
如果目的是能够直接从块设备读取正确的数据,这还不够好。它只保留未来写入所需的存储空间。