再帰的に巡回せずにZFSから大規模ディレクトリを一括削除します。

再帰的に巡回せずにZFSから大規模ディレクトリを一括削除します。

zfsデータセットサブディレクトリのコンテンツを削除したいと思います。これは大量のデータです。プール「nas」の場合、パスは次のようになります。/nas/dataset/certainFolder

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

待たなければならない代わりに、rm -rf certainFolder/ディレクトリへのハンドルを削除して上書きできるようにすることはできません(再作成として選択した場合は、ディレクトリ名が同じでも)。

たとえば、zfsファイルシステムの内部、特にファイルの記録方法がわからない場合は、そのログ/マップに直接アクセスして、ディレクトリが表示されなくなるように正しいエントリを削除できるかどうかを知りたいと思います。 。スペースディレクトリもある種の監査から削除する必要があります。

見つけることができるショートカットがありますか?でも外部3fs、またはこれが再帰削除コマンドが実行する最初の操作、つまりログを盗んで編集することですか?

kill thisDir私は一種のIDを削除し、ディレクトリが表示されなくなった同様のことをしたいと思いますls -la。明らかに、データはまだドライブにありますが、ZFSはとてもクールなので、スペースは再利用(上書き)されます。

私の言葉は私の考えではジブス本当に素敵ですね。私たちはどうですか?理想的には?両手をこすります:-)

私の特定のユースケース(私の好きなものに加えてzfs)はバックアップ/アーカイブ管理です。データは、SMBを介してWin Boxのfreefilesync(AWESOME PROG)を介してzfsプールにzfsにプッシュされます。長い間使用できなかったrm -rf /nas/dataset/certainFolder用語が削除されると停止します。puttyもちろん、続行するには別の端末を開く必要があります。それは時代遅れであり、rm -rfを監視するのは楽しいことではなく、数時間かかることがあります。

たとえば、ハンドルを解放するコマンドを設定して&からstdoutとして印刷する必要があります。それではよさそうです。 もっと現実的にzfs destroy nas/dataset; zfs create -p -o compression=on nas/dataset、@Gilles の応答を考慮した後、数秒でデータセットを再生成します。

答え1

まともなファイルシステムでは、解放されたブロックを追跡することは避けられません。例外なくしかし、ZFSでは、ほとんどすぐにディレクトリを削除する簡単な方法があります。基本的なクリーンアップを「延期」します。技術的には、Gilesの提案と非常に似ていますが、本質的に健全であり、追加のコードは必要ありません。

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

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

答え2

あなたが要求することは不可能です。あるいは、より正確に言えば、ディレクトリとそのファイルを削除するときに支払う必要があります。削除時に費用を支払わない場合は、他の場所で費用を支払う必要があります。

ディレクトリだけを削除するのではなく、ほとんどすぐに削除されます。ディレクトリとその中のすべてのファイルを削除し、同様にすべてのサブディレクトリを繰り返し削除します。ファイルを削除することは、対応するリンク数を減らすことを意味し、リンク数が0に達し、ファイルが0に達しない場合、そのリソース(ファイルの内容とファイルメタデータのブロックとinode(ファイルシステムがinodeテーブルを使用する)場合))がOpenと表示されます。アイドル用。これはディレクトリツリー内のすべてのファイルに対して実行される必要があるため、所要時間は少なくともファイル数に比例します。

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

一般ファイルシステムでGCの動作をシミュレートするには、次のようにします。

mv directory .DELETING; rm -rf .DELETING &

(エラーの確認、停電の回復など、多くの重要な詳細を省略しました。)ディレクトリ名はすぐに存在しなくなり、スペースは徐々に回収されます。

GCなしで削除中の費用の支払いを防ぐもう1つの方法は、割り当て中に費用を支払うことです。ディレクトリツリーを削除済みとしてマークし、ブロックの割り当て中に削除されたディレクトリに移動します。これは、ハードリンクとは調整が困難ですが、ハードリンクを持たないファイルシステムでは、O(1)割り当てコストの増加でこれを行うことができます。ただし、これは非常に一般的なタスク(ファイルの作成または拡大)が高価になり、唯一の利点は、比較的まれなタスク(大きなディレクトリツリーの削除)がより安いということです。

ディレクトリツリーが独自のブロックプールに保存されている場合は、そのディレクトリツリーを一括で削除できます。 (注:私は「プール」という言葉をZFSの「ストレージプール」とは異なる意味で使用します。正確な用語が何であるかわかりません。)これは非常に高速です。しかし、利用可能なスペースで何をしますか?ファイルを個別に削除するよりもはるかに安いですが、別のプールに再割り当てするとコストが発生します。未使用の予約スペースとして残しておくとすぐに回収できません。ディレクトリツリーに対して別々のプールを持つことは、そのプールのサイズを(動的または明示的に)増減するコストが増加することを意味します。ツリーを独自のストレージプールにすると、ツリーの内外にファイルを移動するコストも増えます。

答え3

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

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

答え4

削除し、すばやく再作成したいフォルダが他のデータセットのサブディレクトリではなく独自のデータセットにある場合は、次の操作を実行できます。

zfs rename pool/dataset pool/dataset.old
zfs create -o ...options... pool/dataset
zfs destroy -r pool/dataset.old

pool/dataset既存の製品が廃棄されると、新しい製品をすぐに使用できます。

子データセットを削除したくない場合(たとえばpool/dataset/child、親データセットで名前が変更されたpool/dataset.old/child場合)、状況は少し複雑ですが、子ディレクトリを削除したい場合よりも複雑ではありません。ほとんどのサブディレクトリは削除されても保持されます。ちょうど新しい名前に戻って名前を変更してください。pool/dataset 今後pool/dataset.oldたとえば、破壊zfs rename pool/dataset.old/child pool/dataset/child。同様に、バックmvのサブディレクトリpool/dataset.oldpool/dataset

サブディレクトリの場合は、他のファイルシステムと同様に、次のことができます。

mv subdir subdir.old
mkdir subdir
chmod ... subdir ; chown ... subdir    # if and as required
rm -rf subdir.old/ &

これはGilesが彼の答えで言ったのとほぼ同じです。

同様に、サブサブディレクトリを維持するには、たとえば、rm -rf実行する前にそのサブディレクトリを新しいサブディレクトリに戻しますmv subdir/child subdir/

私は少なくとも1990年代から数十年間この仕事をしてきました。このzfs renameバージョンは同じアプローチの確実な進化にすぎません。 MS-DOSでディレクトリの名前を変更できるかどうかは覚えていませんが、もしそうなら、1980年代のMS-DOSでもそうしたでしょう。

.oldただし、データセットとサブディレクトリの場合はすぐに削除する必要はありません。私は保存したいすべてのアイテムを回復したと確信するまで、または使用しているディスク容量を回復する必要があるまで保持する傾向があります。私は戻りきれないポイントをできるだけ長く遅らせることが大好きです。


しかし、通常、サブディレクトリZFSの代わりにデータセットを使用することをお勧めします。これは、各データセット(圧縮タイプ、クォータ、保存、時間/相対時間、暗号化など)ごとに異なる設定を持つことができ、各データセットは個別に設定できるためです。スナップショットを撮ってバックアップしましたzfs send

しかし、これに対するコストは、ファイルまたはサブディレクトリツリーを別のデータセットに移動することがコピーおよび削除操作であることです。これは、別のディスク、パーティション、LVな​​どの他のファイルシステムに移動するときと同じです。データセットはい実際には、独自のマウントポイントを持つ別の独立したファイルシステムです。バラより同じプール内のある zfs ファイルシステムから別の zfs ファイルシステムにファイルを移動するには?- そこにあるコメント1つが私を今日ここに導きました。

また、注目すべき点は、データセットのマウントポイントが次のようになることです。どこかにファイルシステム階層では、親エントリの下に直接マウントする必要はなく、必要に応じてマウントポイントを変更できます。たとえば、「rpool」という小さなSSDルートプールと「export」という一括データ用の大規模HDDプールがある場合は、エクスポートするためにrpoolの大きなサブディレクトリ(およびデータセット)を移動して同じ場所にインストールすることができます。場所。例えば

zfs create export/share-doc
mv /usr/share/doc/* /export/share-doc/
zfs set mountpoint=/usr/share/doc export/share-doc

(これは単純化された例です。実際、私はfs階層をコピーする傾向があります。たとえば、エクスポート/usr、エクスポート/usr/share、エクスポート/usr/share/docのデータセットを作成します。)プールのトップレベルを維持します。 (b)他のサブディレクトリまたはデータセットをそこに移動する必要がある場合)

データセット名と階層とマウントポイントの違いを理解することが重要です。データセットを繰り返し削除すると、インストールされている場所に関係なく、そのサブデータセットも削除されます。したがって、維持したい子供の名前を変更することを忘れないでください。

関連情報