ext3のファイル最大長
Rev.3を表示中。最新版はこちら。
ファイルサイズは、物理inodeに設定できるブロックスロットの総数で決まり、最大サイズはブロックスロット総数×ブロックサイズとなります。ext3ファイルシステムマウント時、ext3_fill_super()で、struct super_blockのメンバs_maxbytesに、ext3_max_size()で取得したファイルの最大サイズ値を設定されます。
ext3のスロットは4バイトで、直接設定できる12個のスロットに、1階層ノード、2階層ノード、3階層ノードを1つづつ有しています。階層となるノードのブロックIDが設定され、従って、下位層はブロックサイズに応じたスロット数ないしノード数を有することになります。ビット演算でのこなれた実装のため、取っ付き難いかもしれませんが、実態はいたってシンプルです。
static int ext3_fill_super (struct super_block *sb, void *data, int silent) { : sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits); : }bitsはビットシフトでのブロックサイズです。まずresにスロット数を加算していきます。
res = EXT3_NDIR_BLOCKSは直接のスロットID数です。 res += 1LL << (bits-2)は1階層でのスロットID数です。 res += 1LL << (2*(bits-2))は2階層でのスロットID数です。 res += 1LL << (3*(bits-2))は3階層でのスロットID数です。bits-2でシフトするのは、まず<<bitsで、ブロックサイズとし、<< -2で1スロット4バイトのため、ブロックサイズを4バイトで除算することで、ブロックサイズに有するスロット数を算出することになります。それを1/2/3階層に応じて求めます。
で、resは総スロット数となり、1スロットが1ブロックで、res <<= bitsで総サイズとなります。
#define EXT3_NDIR_BLOCKS 12 static loff_t ext3_max_size(int bits) { loff_t res = EXT3_NDIR_BLOCKS; int meta_blocks; loff_t upper_limit; upper_limit = (1LL << 32) - 1; upper_limit >>= (bits - 9); meta_blocks = 1; meta_blocks += 1 + (1LL << (bits-2)); meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); upper_limit -= meta_blocks; upper_limit <<= bits; res += 1LL << (bits-2); res += 1LL << (2*(bits-2)); res += 1LL << (3*(bits-2)); res <<= bits; if (res > upper_limit) res = upper_limit; if (res > MAX_LFS_FILESIZE) res = MAX_LFS_FILESIZE; return res; }上で求めたresサイズは、ファイルシステムとしての最大値upper_limit以下でなければなりません。またページキャッシュに依存するカーネルとしての最大サイズ以下でなければなりません。
補足
upper_limit = (1LL << 32) - 1は、LBAが32ビットということではないでしょうか。でupper_limitがファイルシステムとしての最大容量ということです。LBAということでセクタ数(通常512バイト)で、それを (bits - 9);シフトすることでブロック数に変換します。meta_blocks = 1は階層1のスロット情報のためのブロックで、以下階層2でのスロット情報のブロック数、階層3でのスロット情報のブロック数で、
meta_blocksは、スロット情報を設定するためのブロックの総数となり、それを upper_limit -= meta_blocksで、upper_limitは、実データのみのブロック数となります。upper_limit <<= bitsでそのサイズです。従って物理的にupper_limitを超えたファイルサイズは作成できないということだと思いますが、そうならスーパブロックとかiノードビットマップブロックは考慮しなくていいのでしょうか? なお、ext2についても同様な実装となっていますが、upper_limitにかかる処理はインプリメントされていません。