ディレクトリが確保したブロックはディレクトリエントリ削除後も解放されない

Linuxext2では,ディレクトリエントリ用に確保されたブロックは ディレクトリエントリ削除後も解放されないみたいだ. 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パフォーマンスが落ちるわけではないようだ.