ディレクトリが確保したブロックはディレクトリエントリ削除後も解放されない
Linuxのext2では,ディレクトリエントリ用に確保されたブロックは ディレクトリエントリ削除後も解放されないみたいだ. FreeBSDのufsの場合,ファイル削除直後には解放されないが, その後新しいディレクトリエントリを作成すると不要ブロックは解放される.
どちらも甚だいい加減な方法で確認した話なので,嘘かもしれない.
ext2に関するドキュメント JF: Linux Kernel 2.6 Documentation: ext2.txt の「ディレクトリ」の項には以下の記述がある.
より多くのファイルを保持するためにディレクトリブロックが割当てられたな らば、現在の実装はその領域が空になっても空きブロックを削除しません。
例えば,新しく作成したディレクトリのstat情報は以下のようになる.
$ mkdir testdir $ stat testdir File: `testdir/' Size: 4096 Blocks: 8 IO Block: 4096 ディレクトリ
このディレクトリの下にたくさんファイルを作ると, 当然ディレクトリi-nodeが確保しているブロック数は増える.
$ cd testdir $ perl -e 'foreach (1...1000) { system("touch file.$_"); }' $ cd .. $ stat testdir File: `testdir/' Size: 16384 Blocks: 32 IO Block: 4096 ディレクトリ
じゃあ,ファイルを削除してみる. 確保されているブロックは解放されるかな?
$ rm testdir/*
$ stat testdir
File: `testdir/'
Size: 16384 Blocks: 32 IO Block: 4096 ディレクトリ
やっぱり変わらない. ディレクトリエントリが削除されても,ブロックは解放されないのだ.
ディレクトリの保持するブロック数が大きくなると, その下のファイルへのアクセスが遅くなるんじゃないかという疑問がある. 簡単ではあるがちょっと計ってみようと思う.
$ cd testdir_1000/ (1000個ファイルを格納) $ perl -e 'foreach(1..100){ system("stat file.$_ > /dev/null") }' real 0m1.967s user 0m1.569s sys 0m0.300s $ cd testdir_100000/ (100000個ファイルを格納) $ perl -e 'foreach(1..100){ system("stat file.$_ > /dev/null") }' real 0m1.953s user 0m1.590s sys 0m0.259s $ perl -e 'foreach(30000..30100){ system("stat file.$_ > /dev/null") }' real 0m1.965s user 0m1.598s sys 0m0.294s $ perl -e 'foreach(70000..70100){ system("stat file.$_ > /dev/null") }' real 0m2.123s user 0m1.545s sys 0m0.304s
どれも,あんまり変わらない. ファイルシステムキャッシュやHDDキャッシュの考慮が些か微妙な試験だが,ディレクトリの確保ブロック数が少し多くなっても,急激にディスクI/Oパフォーマンスが落ちるわけではないようだ.