スパース ファイルのゼロ化されたブロックを再利用するにはどうすればよいでしょうか?
-
22-09-2019 - |
質問
ファイルの一部に 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_punchhole
Linux 用 (私がたまたま見つけたディスカッション)。
解決
現時点では、NTFS のみがホールパンチをサポートしているようです。これは、歴史的にほとんどのファイルシステムで問題となってきました。私の知る限り、POSIX は穴を開けるための OS インターフェイスを定義していないため、標準の Linux ファイルシステムはどれもそれをサポートしていません。NetApp は、Windows を介したホールパンチをサポートしています。 ワフル ファイルシステム。これに関する素晴らしいブログ投稿があります ここ.
あなたの問題については、他の人が指摘したように、唯一の解決策は、ゼロを含むブロックを残してファイルを移動することです。はい、遅くなるでしょう。または、これを実行する Linux 上のファイルシステム用の拡張機能を作成して、 提出する ある パッチ に 良い人たち Linuxカーネルチームの一員です。;)
編集: XFS はホールパンチをサポートしているようです。チェック このスレッド.
もう 1 つの非常にひねったオプションは、 ファイルシステムデバッガ ファイル内のゼロ設定されたブロックを指すすべての間接ブロックに穴を開けます (スクリプトを作成できるかもしれません)。次に fsck を実行すると、関連するすべてのブロック数が修正され、孤立したブロック (ゼロ化されたブロック) がすべて収集され、lost+found ディレクトリに配置され (スペースを再利用するために削除できます)、ファイルシステム内の他のプロパティが修正されます。怖いですよね?
免責事項:これはご自身の責任で行ってください。あなたが被ったデータ損失については責任を負いません。 ;)
他のヒント
fallocate
と呼ばれるシステムコールを追加したかのようにはそれが表示されます。個々のファイルシステムにおける実装は、ブロックの大きい連続数を事前割り当てのためにこれを使用する能力に焦点を当てるように見える。
があり、後者のみに焦点を当てることposix_fallocate
コールもあり、穴あけに使用可能ではない。
ロンYorston の申し出いくつかのソリューション。しかし、それらはすべてFSが読み取り専用でマウント(またはそれをアンマウント)スパース化が行われている間のいずれかの関与します。またはちょうど0でない元のものとチャンク間でコピーして、新しくスパースファイルを元のファイルを置き換え、その後、新しいスパースファイルを作ります。
これは本当にかかわらず、あなたのファイルシステムに依存します。我々はすでにNTFSはこれを処理することを見てきました。私はウィキペディアリストは透明の圧縮を扱うようを他のファイルシステムのいずれかが正確に行うだろうと想像します同じ - これは、すべての後に、透過的にファイルを圧縮することと同じです。
あなたは、この新しい領域がまばらな地域であることを意図していることをファイルシステムに指示する必要があり、ファイルの一部の領域「ゼロ」した後。だから、NTFSの場合は、もう一度その領域のためのDeviceIoControl()を呼び出す必要があります。少なくとも私は私のユーティリティでこの方法を実行します。「sparse_checker」の
私にとっては大きな問題がまばらな地域のバックの設定を解除する方法です。)
よろしく
この方法は安価ですが、効果があります。:-P
- 必要なホールを超えたすべてのデータをメモリ (または別のファイルなど) に読み込みます。
- ファイルを穴の先頭まで切り詰めます (
ftruncate
あなたの友だちです)。 - 穴の端まで探します。
- データを再度書き込みます。
方法に類似debugfsのか、fsckの中で直接ファイルシステムおよび編集、ファイルシステムをumount。通常は、各使用済みのFS用のドライバが必要になります。
あなたがしようとする論理的なものであるとの終わった部分に(参照質問のように)ゼロを書き込むように思えます。ここでは、「リリース」「未使用」の部分にだけことを行いNTFSスパースファイルのためのMSDNの質問へのリンク。 YMMVます。