web-dev-qa-db-ja.com

再帰的に走査せずにZFS上の大きなディレクトリを一括削除する

大量のデータがあるディレクトリを削除したい。これは私のバックアップアレイです。これは[〜#〜] zfs [〜#〜]ファイルシステム、線形スパン、「san」と呼ばれる単一のプールです。 Sanは/sanにマウントされているので、/ san/thispc/certainFolderを一括削除します

$ du -h -d 1 certainFolder/
1.2T    certainFolder/

私がrm -rf certainFolder/を待つ必要があるのではなく、そのディレクトリへのハンドルを破棄して、上書き可能にすることができます(再作成することを選択した場合でも、同じdir名でも)??

したがって、たとえばzfs fs internal mgmntがディレクトリをどのようにマップするかを具体的に理解していませんが、たとえば、そのマップがたとえばを見つけ、適切なエントリを削除すると、たとえば、ディレクトリは表示されなくなり、ディレクトリが以前保持していたスペースはある種の監査からも削除されました。

ext fsの場合でも、これを行う簡単な方法はありますか?それとも、再帰的な削除コマンドが最初に行う必要があること、つまり、ジャーナルを調べて編集することですか?

kill thisDirのようなものを実行して、ある種のIDを削除するだけで、ディレクトリがls -laに表示されなくなり、データがドライブに残っていることを期待しています明らかに、しかし、ZFSはそのように格好良いので、スペースは今再利用(上書き)されますか?

zfsは本当にクールだと思いますが、どうすれば実行できますか?理想的には?一緒に手をこする:-)

私の特定のユースケース(zfsへの私の愛情以外に)は、バックアップアーカイブの管理です。このバックアップディレクトリは、Windowsボックスのfreefilesync(AWESOME PROG)を介してsmbファイル共有にプッシュされますが、古いファイルが移動するバージョンディレクトリもあります。バージョンにコピーされた、メインバックアップにある最上位ディレクトリを削除します-たとえば、 /san/version/someStuff、PuTTY端末からのrm -rf /san/version/someStuff/*の隔月クリーンアップとして、今度は別の端末を開く必要があります。毎回そうしたくないので、無駄にrm -rfを監視する必要があります。

つまり、ハンドルを解放するようにコマンドを設定してから、標準出力に出力する必要があります。 より現実的に、@ Gillesからの応答からの思考の後、数秒でデータセットを再作成しますzfs destroy san/version; zfs create -p -o compression=on san/version

9
Brian Thomas

適切なファイルシステムでは解放されたブロックの追跡は避けられず、ZFSは 例外なし です。 ただし、ZFSでは、基礎となるクリーンアップを「延期」することにより、ほぼ瞬時にディレクトリを削除する簡単な方法があります。それは技術的にGillesの提案に非常に似ていますが、追加のコードを必要とせずに本質的に信頼性があります。

ディレクトリを削除する前にファイルシステムのスナップショットを作成すると、その下で探索/解放する必要がないため、ディレクトリの削除は非常に速くなり、すべてスナップショットで参照されます。その後、バックグラウンドでスナップショットを破棄して、スペースを徐々に回復することができます。

d=yourPoolName/BackupRootDir/hostNameYourPc/somesubdir
zfs snapshot ${d}@quickdelete && { 
    rm -rf /${d}/certainFolder
    zfs destroy ${d}@quickdelete & 
}
12
jlliagre

あなたが求めていることは不可能です。または、より正確には、ディレクトリとそのファイルを削除する際にコストがかかります。削除時に支払わなかった場合は、別の場所で支払う必要があります。

ディレクトリを削除するだけではなく、ほぼ瞬時に削除されます。ディレクトリとその中のすべてのファイルを削除し、同様にそのすべてのサブディレクトリを再帰的に削除します。ファイルを削除するということは、リンクカウントをデクリメントし、リンクカウントが0に達し、ファイルが存在しない場合、リソース(ファイルの内容とファイルメタデータに使用されるブロック、およびファイルシステムがiノードテーブルを使用する場合はiノード)を空きとしてマークすることを意味します開いた。これはディレクトリツリー内のすべてのファイルに対して実行する必要がある操作であるため、かかる時間は少なくともファイル数に比例します。

リソースを無料としてマークするコストを遅らせることができます。たとえば、ガベージコレクションされたファイルシステムがあり、そこに含まれるファイルを削除せずにディレクトリを削除できます。ガベージコレクターを実行すると、ディレクトリ構造を介して到達できないファイルが検出され、空きファイルとしてマークされます。ガベージコレクションされたファイルシステムでrm -f directory; garbage-collectを実行すると、従来のファイルシステムでrm -rfと同じことを行いますが、トリガーは異なります。 GCはめったに必要とされない追加の複雑さであるため、ガベージコレクションされたファイルシステムはほとんどありません。ファイルシステムに空きブロックが必要で、ブロックが見つからない場合、GCのタイミングはいつでもかまいません。そのため、操作のパフォーマンスは、操作だけでなく過去の履歴にも依存するため、通常は望ましくありません。実際の空き容量を取得するには、ガベージコレクターを実行する必要があります。

通常のファイルシステムでGCの動作をシミュレートする場合は、次のように実行できます。

mv directory .DELETING; rm -rf .DELETING &

(エラーチェック、停電への耐性など、重要な詳細の多くは省略しました。)ディレクトリ名はすぐに存在しなくなります。スペースは徐々に再利用されます。

GCなしで削除中にコストを支払うのを回避する別のアプローチは、割り当て中に支払うことです。ディレクトリツリーを削除済みとしてマークし、ブロックを割り当てるときに削除されたディレクトリを通過します。これはハードリンクとの調整が困難ですが、ハードリンクのないファイルシステムでは、O(1)割り当てのコストが増加します。ただし、これは非常に一般的な操作になります(ファイルの作成または拡大)はより高価で、唯一の利点は比較的まれな操作(大きなディレクトリツリーの削除)がより安価であることです。

ディレクトリツリーが独自のブロックのプールとして格納されている場合、ディレクトリツリーを一括削​​除できます。 (注:ZFSの「ストレージプール」とは別の意味で「プール」という単語を使用しています。適切な用語が何なのかわかりません。)それは非常に高速である可能性があります。しかし、空きスペースをどうしますか?別のプールに再割り当てすると、コストがかかりますが、ファイルを個別に削除するよりもはるかに少なくなります。スペースを未使用の予約スペースとして残しておくと、すぐに再利用できません。ディレクトリツリーに個別のプールを使用すると、そのプールのサイズを(その場でまたは明示的に)増加または減少させるための追加コストが発生します。ツリーを独自のストレージプールにすると、ファイルをツリーに移動したりツリーから移動したりするコストも増加します。

高速にする必要がある場合は、新しい一時ディレクトリmvをその下のディレクトリに生成して、一時的に再帰的に削除します。

t=`mktemp -d`
mv certainFolder $t/
rm -rf $t &
1
Simon Richter