FAT32で65534個目のファイルが作れない
FAT32フォーマットしたストレージではルート以外のディレクトリ・エントリ数の上限(ファイル数上限と思えばよい)は 2^16-2 == 65534 (マイナス2は .
と ..
が強制的に作られるので)というのが通説である.特に実装に当たった訳ではないが,ググって出てくるあらゆる情報源がそう書いてるので無批判に鵜呑みにすることに決めた.ところが私の4 GBマイクロSDカードでは 2^16-3 == 65533 で打ち止めになってしまう.なぜだ...
$ cd /media/usb1 $ mkdir many $ cd many $ dd if=/dev/urandom of=/tmp/1.DAT count=1 $ ruby -r fileutils -e '(1..65534).each{|i| FileUtils.cp("/tmp/1.DAT","%d.DAT"%i)}'
これが3時間くらい待った挙句 65534.DAT を作るときに「空きがないよ」と言ってエラーになる.ファイル名は8.3形式でないとディレクトリ・エントリの消費が激しい (VFAT) と聞いて %d.DAT
という書式にしたんだが,最初 %d
でやってたときと差はなかった感じ.マイクロSDカードはWindows XPにて "FAT" にフォーマットしたもの.実験環境はDebian GNU/Linux Squeeze (2.6.32-5-amd64)
rsyncだと競合問題の関係でファイル書き込みが終わるまで一時ファイルを作るが,上のスクリプトでその問題はないはず.実際
$ /bin/ls -f|egrep -v '^[[:digit:]]*\.DAT$'
とかすると, .
と ..
しか出ないし, /bin/ls -f|wc -l
は 65535 だもんな... (-f
は .
と ..
を含む.)なのに touch 65534.DAT
が失敗.
Linux VFATドライバでのマウント時にはI/O charsetがどうとかの話があるが,その辺りでVFATが勝手に発動してエントリを余分に消費してるのか? ちなみにVFATとは,FATのファイル名欄がフラグメンテーションしてるとも言うべき後付け感溢れる方式である.しかしMSはそのようにあらゆる犠牲を払って互換性を維持して今の地位を築いたのだなぁ...
ファイルシステムにおけるB-treeの威力を実感しようと遊び始めたんだが,これが気になってベンチマークどころではなくなってしまった.うーむ.