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....

編集 -

ファイルを書き換えたり、ファイルをコピーしたりしたくないことをさらに限定させてください。以前に割り当てられたブロックを in situで何らかの形で解放できない場合は、それで構いませんが、それが実際に可能かどうかを判断したいと思います。いいえ。この時点で「いや、そうじゃない」みたいな。私はsys_punchholeLinux を探していると思います (私がたまたま見つけた議論)。

4

7 に答える 7

10

fallocateファイルに「穴を開ける」ために呼び出されるsyscallがLinuxに追加されたかのように見えます。個々のファイルシステムの実装は、これを使用してより多くの連続したブロックを事前に割り当てる機能に焦点を当てているようです。

posix_fallocate後者だけに着目し、穴あけには使えないコールもある。

于 2010-07-24T22:39:25.540 に答える
4

現在、NTFSのみがホールパンチングをサポートしているようです。これは歴史的にほとんどのファイルシステムで問題になっています。私の知る限り、POSIXはパンチ穴を作るためのOSインターフェースを定義していないので、標準のLinuxファイルシステムはどれもそれをサポートしていません。NetAppは、 WAFLファイルシステムでWindowsを介した穴あけをサポートしています。これについての素晴らしいブログ投稿がここにあります

あなたの問題については、他の人が指摘しているように、唯一の解決策は、ゼロを含むブロックを除外してファイルを移動することです。ええ、それは遅くなるでしょう。または、これを行うLinux上のファイルシステムの拡張機能を作成し、Linuxカーネルチームの優秀な人々にパッチ送信します。;)

編集: XFSはホールパンチングをサポートしているようです。このスレッドを確認してください。

もう1つの本当にねじれたオプションは、ファイルシステムデバッガーを使用して、ファイル内のゼロ化されたブロックを指すすべての間接ブロックに穴を開けることです(おそらくそれをスクリプト化できます)。次に、fsckを実行して、関連するすべてのブロックカウントを修正し、孤立したブロック(ゼロにされたブロック)をすべて収集して、それらをlost + foundディレクトリに配置し(スペースを再利用するために削除できます)、ファイルシステムの他のプロパティを修正します。怖いですよね?


免責事項:これは自己責任で行ってください。私はあなたが被るいかなるデータ損失についても責任を負いません。;)

于 2010-01-08T07:05:46.533 に答える
2

RonYorstonはいくつかのソリューションを提供しています。ただし、これらはすべて、スパース化が行われている間に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 に答える