如何在 Linux 上消除稀疏文件中的漏洞?

如何在 Linux 上消除稀疏文件中的漏洞?

如何在 Linux 上删除稀疏文件中的所有漏洞?在 Windows 上,我认为程序是

fsutil sparse setflag <file> 0

Linux 的对应版本是什么?

(我知道cp <file> <file>.cp; rm <file>; mv <file>.cp <file>;如果可用磁盘空间允许的话可以完成这项工作,但我猜 Linux 有一种现成的方法可以完成它?像 Windows 一样?)

答案1

fallocate -l <length> <file>可能会实现这一点;虽然它没有告诉文件系统明确地用零填充空洞,但它确实分配空间对他们来说。比较:

[make a sparse file]
$ echo yay | dd bs=1 seek=1G of=test.file

[list extents]
$ filefrag -v test.file
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:   262144..  262144:  902523324.. 902523324:      1:     262144: last,eof

[allocate space]
$ fallocate -l $(stat -c %s test.file) test.file

[list extents again]
$ filefrag -v test.file
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..  196607: 2219092376..2219288983: 196608:             unwritten
   1:   196608..  262143: 2219301264..2219366799:  65536: 2219288984: unwritten
   2:   262144..  262144:  902523324.. 902523324:      1: 2219366800: last,eof

使用filefrag -v <file>xfs_io -r -c "fiemap -v" <file>列出文件的范围。在此示例中,fallocate 之后不再有漏洞;它们现在被“未写入”的范围覆盖,文件系统将继续在读取时立即返回零,但现在分配有特定的物理块。

从技术上讲,可以向 fallocate 添加一个选项,该选项使用 FIEMAP 列出漏洞和/或“未写入”的范围并用零填充它们,但不幸的是,它目前还没有这个选项,需要手动指定零填充偏移量/长度。


  • 如果文件恰好在和之间被截断stat -c %sfallocate则后一个操作将使其再次增长到之前的大小。

    如果您希望文件再次增大,那么您可以避免使用这种方法-n/--keep-size(这种方法只预分配空间,但不会使文件增大),尽管我对 Linux 中分配 EOF 以外空间的确切语义不太清楚。(我想这类似于 Windows 的“fsutil file setEOF/setValidData”。)

    另一方面,如果文件成长在两次操作之间,它不会被截断;新添加的数据(或漏洞)将不会受到 fallocate 的影响。(也就是说,您不会丢失任何数据;最坏的情况是您只需要再次执行此操作即可摆脱新添加的漏洞。)

  • 请注意cp– 在最近的 GNU Coreutils 版本中,它将自动尝试使用 SEEK_HOLE 来保持稀疏性。您可能需要使用 来cp --sparse=never防止这种情况。

  • 此外,从 Coreutils 9.x 开始,如果文件系统支持cp foo bar,甚至cat foo > bar会自动使用 FICLONE 或 copy_file_range() 操作来克隆文件而无需实际复制其数据,例如在 XFS 或 Btrfs 或 ZFS 上(类似于 ReFS 中的“块克隆”功能)。

    如果发生这种情况,“副本”将准确保留文件原始的稀疏性,您将shared在 filefrag 的输出中看到每个范围的标志。您可以使用cp --reflink=never它来防止这种情况。

    (fallocate 系统调用有一个标志来取消共享范围,但它尚未通过fallocate命令行工具公开,尽管您可以通过xfs_io具有“funshare”子命令来执行此操作。)

相关内容