如何回收稀疏文件的归零块?

时间:2009-12-30 21:59:11

标签: linux file filesystems sparse-file

考虑一个稀疏文件,其中1s写入文件的一部分。

我想回收磁盘上这些1的实际空间,因为我不再需要稀疏文件的那部分。包含这些1的文件部分应该成为一个“洞”,就像1s自己写的那样。

为此,我将区域清除为0。这样做回收磁盘上的块。

如何实际制作稀疏文件,再次稀疏?

此问题类似于this one,但该问题没有被接受的答案。

考虑在股票Linux服务器上运行的以下事件序列:

$ cat /tmp/test.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char **argv) {
    int fd;
    char c[1024];

    memset(c,argc==1,1024);

    fd = open("test",O_CREAT|O_WRONLY,0777);
    lseek(fd,10000,SEEK_SET);
    write(fd,c,1024);
    close(fd);

    return 0;
}

$ gcc -o /tmp/test /tmp/test.c

$ /tmp/test

$ hexdump -C ./test
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002710  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
*
00002b10

$ du -B1 test; du -B1 --apparent-size test
4096        test
11024       test

$ /tmp/test clear

$ hexdump -C ./test
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002b10

$ du -B1 test; du -B1 --apparent-size test
4096        test
11024       test

# NO CHANGE IN SIZE.... HMM....

编辑 -

让我进一步说明我不想重写文件,复制文件等。如果不能以某种方式释放以前分配的块原位,那么就这样吧,但是我我想确定这是否真的可能。在这一点上,似乎“不,它不是”。我想我正在为Linux寻找sys_punchhole(我刚刚偶然发现了这些讨论)。

7 个答案:

答案 0 :(得分:9)

答案 1 :(得分:4)

现在似乎只有NTFS支持打孔。这在历史上一直是大多数文件系统的问题。据我所知,POSIX没有定义用于打孔的OS接口,因此没有一个标准Linux文件系统支持它。 NetApp在其WAFL文件系统中支持通过Windows进行打孔。有一篇关于这个here的好文章。

对于您的问题,正如其他人所指出的那样,唯一的解决方案是移动文件,省略包含零的块。是的,它会变慢。或者在Linux上为您的文件系统编写一个扩展,并在submit patch为Linux内核团队中的good folks编写一个扩展名。 ;)

编辑:看起来XFS支持打孔。检查this thread

另一个真正扭曲的选项可以是使用filesystem debugger去打孔并在所有间接块中打孔,这些块指向文件中的清零块(也许你可以编写脚本)。然后运行fsck,它将纠正所有相关的块计数,收集所有孤立的块(归零的块)并将它们放入lost + found目录(您可以删除它们以回收空间)并更正文件系统中的其他属性。可怕,是吗?


免责声明:自行承担风险。我对您承担的任何数据丢失概不负责。;)

答案 2 :(得分:2)

Ron Yorston提供了多种解决方案;但它们都涉及在稀疏发生时安装FS只读(或卸载它);或者创建一个新的稀疏文件,然后复制那些不仅仅是0的原始块,然后用新的sparsified文件替换原始文件。

这实际上取决于你的文件系统。我们已经看到NTFS处理这个问题了。我认为处理透明压缩的任何其他文件系统Wikipedia lists都会完全相同 - 毕竟,这相当于透明地压缩文件。

答案 3 :(得分:2)

在“归零”文件的某个区域后,您必须告诉文件系统该新区域是一个稀疏区域。因此,在NTFS的情况下,您必须再次为该区域调用DeviceIoControl()。至少我在我的实用程序中这样做:"sparse_checker"

对我来说,更大的问题是如何取消稀疏区域:)。

此致

答案 4 :(得分:1)

这种方式很便宜,但它有效。 :-P

  1. 将您想要的所有数据读入内存(或其他文件或其他任何内容)。
  2. 将文件截断到洞的开头(ftruncate是你的朋友)。
  3. 寻找洞的尽头。
  4. 重新写入数据。

答案 5 :(得分:0)

以类似的debugfs或fsck的方式直接卸载文件系统并编辑文件系统。通常你需要每个使用过的fs的驱动程序。

答案 6 :(得分:-1)

看起来像写零(如引用的问题)到你完成的部分是一个合乎逻辑的尝试。这里有一个指向NTFS稀疏文件的MSDN问题的链接,它只是为了“释放”“未使用”的部分。 YMMV。

http://msdn.microsoft.com/en-us/library/ms810500.aspx