【问题标题】:How does one reclaim zeroed blocks of a sparse file?如何回收稀疏文件的零块?
【发布时间】:2010-12-31 06:20:28
【问题描述】:

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

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

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

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

此问题类似于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(我刚刚偶然发现的讨论)。

【问题讨论】:

  • 从我读过的稀疏文件来看,关键的决定因素不是块被 0 填充,而是它从未被写入。你有任何相反的参考吗?
  • 稀疏文件的某些部分从未被写入没有分配的块。但是,我的问题是,一旦我分配了一个或多个块,我该如何释放它们?我不再需要稀疏文件的一部分,并且想归还以前分配的块。但我不能。嘘。
  • cp --sparse=always ... 稀疏文件是基于系统管理存储方式的黑客;依赖黑客从来都不是一个好主意。如果您需要可能有碎片来来去去的稀疏数据结构,我建议您寻找这样的结构或自己编写。
  • 我想您也可以自己处理 inode 条目……自 90 年代初以来,还没有接触过该级别的文件系统,所以没有更多可提供的了。

标签: linux file filesystems sparse-file


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

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

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

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

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


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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      问候

      【讨论】:

        【解决方案5】:

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

        1. 将所有数据通过所需的孔读入内存(或其他文件,或其他)。
        2. 将文件截断到孔的开头(ftruncate 是你的朋友)。
        3. 寻找到洞的尽头。
        4. 重新写入数据。

        【讨论】:

        • 哎哟。因此,让我进一步说明我正在寻找可以很好地“扩展”的东西。 :) 我不想重写文件、复制文件等。如果无法以某种方式就地释放先前分配的块,那就这样吧,但我想确定这是对还是错。跨度>
        • 这取决于您的文件系统。我们已经看到 NTFS 处理这个问题。我想任何其他文件系统 [Wikipedia lists][1] 处理透明压缩都会做同样的事情 - 毕竟,这相当于透明压缩文件。 [1]en.wikipedia.org/wiki/…
        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

          • 我按照“脚本”输出中的说明进行操作。
          • 阅读文章。 Windows 有一个特殊的调用来释放这些块。 Linux 可能也是如此。
          猜你喜欢
          • 1970-01-01
          • 2019-05-03
          • 2014-02-25
          • 1970-01-01
          • 2018-01-19
          • 1970-01-01
          • 1970-01-01
          • 2014-08-12
          • 2014-10-03
          相关资源
          最近更新 更多