14

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

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

为此,我将该区域清除为 0。这不会回收磁盘上的块。

我实际上如何使稀疏文件再次变得稀疏?

这个问题与这个问题类似,但该问题没有公认的答案。

考虑在普通 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....

编辑 -

让我进一步说明我不想重写文件、复制文件等。如果无法以某种方式就地释放先前分配的块,那就这样吧,但我想确定这是否真的可行或不是。在这一点上似乎“不,不是”。我想我正在寻找sys_punchholeLinux(我刚刚偶然发现的讨论)。

4

7 回答 7

10

似乎 linux 已经fallocate在文件中添加了一个名为“打孔”的系统调用。单个文件系统中的实现似乎专注于使用它来预分配更大的连续数量的块的能力。

也有posix_fallocate只关注后者的调用,不能用于打孔。

于 2010-07-24T22:39:25.540 回答
4

现在看来只有 NTFS 支持打孔。在大多数文件系统中,这在历史上一直是一个问题。据我所知,POSIX 没有定义操作系统接口来打孔,因此没有一个标准的 Linux 文件系统支持它。NetApp 在其WAFL文件系统中支持通过 Windows 打孔。这里有一篇很好的博客文章。

对于您的问题,正如其他人所指出的那样,唯一的解决方案是移动文件而忽略包含零的块。是的,它会很慢。或者在 Linux 上为您的文件系统编写一个扩展来执行此操作,并将补丁提交给Linux 内核团队中的好人。;)

编辑:看起来 XFS 支持打孔。检查这个线程

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


免责声明:这样做需要您自担风险。我不对您造成的任何数据丢失负责。;)

于 2010-01-08T07:05:46.533 回答
2

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

不过,这实际上取决于您的文件系统。我们已经看到 NTFS 处理这个问题。我想维基百科列出的任何其他处理透明压缩的文件系统都会做同样的事情——毕竟,这相当于透明地压缩文件。

于 2009-12-30T22:26:48.650 回答
2

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

对我来说,更大的问题是如何重新设置稀疏区域:)。

问候

于 2010-06-23T13:01:46.063 回答
1

这种方法很便宜,但很管用。:-P

  1. 将所有数据通过你想要的洞读入内存(或另一个文件,或其他)。
  2. 将文件截断到洞的开头(ftruncate是你的朋友)。
  3. 寻找到洞的尽头。
  4. 将数据重新写入。
于 2009-12-30T22:16:06.613 回答
0

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

于 2010-01-08T09:44:06.887 回答
-1

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

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

于 2009-12-30T22:07:51.163 回答