lsコマンドの表示について(ディレクトリのサイズ)
lsコマンドの表示について(ディレクトリのサイズ)というのがあった。新規に作成したディレクトリのサイズが4096の倍数で表示されるというものだ。実際新規にディレクトリを作成してls -lとしてみると、確かに4096で、その下にファイルを作成しても4096のままである。
Takeshi Kusune さんが実装にもとずいて説明されている。ディレクトリもファイルと同じ扱いをする。ファイル同じようにiノードをもつ。(ただし、file_operetion,inode_operatinのコールバック関数は異なる。)そしてファイルと同じようにデータブロックをもつ。
fs/ext3/namei.cのstatic int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)で
配下にファイルをどんどん作成していって、4096を超えた場合別のデータブロックを使うことになる。その場合のサイズは4096*2となるか?
ext3_add_entryはext3ファイルシステムのディレクトリへの登録処理です。まず現ブロック数を取り出して、最初のブロックからの先頭から、add_dirent_to_buf関数で、新規ファイル名が登録できるスペースがあるかどうかを探していきます。ディレクトリフォーマットは、iノード、レコードサイズ、ファイル名サイズ、ファイルタイプ、ファイル名の順に登録されており、ファイルを削除は、前のファイル名のレコードサイズを削除するファイルのレコードサイズまで拡張することで行っているそうです。ですから、登録はディレクトリの先頭から空きスペースを探しています。
もし空きスペースなければ、次にブロックNOを引数にして、ext3_appendがよばれています。この関数で新規ブロックを確保し、再度add_dirent_to_bufでそのブロックに追加ファイル名の登録となるようです。
p/s
inodeのディレクトリ構造からみて、ディレクトリサイズは意味がない。
下記はディレクトリエントリの構造のイメージである。
Takeshi Kusune さんが実装にもとずいて説明されている。ディレクトリもファイルと同じ扱いをする。ファイル同じようにiノードをもつ。(ただし、file_operetion,inode_operatinのコールバック関数は異なる。)そしてファイルと同じようにデータブロックをもつ。
fs/ext3/namei.cのstatic int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)で
inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;確かにiノードのi_sizeに自スーパブロックのブロックサイズを設定している。i_sb->s_blocksizeはファイルシステム登録register_filesystem時に、ファイルシステム毎に設定するスーパブロック情報でコールバック関数で設定される。mkfs時の設定値で通常は4096だ。ディレクトリも実際のサイズを有しているわけだから、ファイルのように1バイト単位でサイズを表示させることは可能だと思う。ディレクトリはこのデータブロックに配下のファイルのiノードとファイル名を記述しており、ファイルと同じように実際のサイズを有している。
配下にファイルをどんどん作成していって、4096を超えた場合別のデータブロックを使うことになる。その場合のサイズは4096*2となるか?
ext3_add_entryはext3ファイルシステムのディレクトリへの登録処理です。まず現ブロック数を取り出して、最初のブロックからの先頭から、add_dirent_to_buf関数で、新規ファイル名が登録できるスペースがあるかどうかを探していきます。ディレクトリフォーマットは、iノード、レコードサイズ、ファイル名サイズ、ファイルタイプ、ファイル名の順に登録されており、ファイルを削除は、前のファイル名のレコードサイズを削除するファイルのレコードサイズまで拡張することで行っているそうです。ですから、登録はディレクトリの先頭から空きスペースを探しています。
もし空きスペースなければ、次にブロックNOを引数にして、ext3_appendがよばれています。この関数で新規ブロックを確保し、再度add_dirent_to_bufでそのブロックに追加ファイル名の登録となるようです。
static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
struct inode *inode)
{
・・・・・・・
blocks = dir->i_size >> sb->s_blocksize_bits;
for (block = 0, offset = 0; block < blocks; block++) {
bh = ext3_bread(handle, dir, block, 0, &retval);
if(!bh)
return retval;
retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
if (retval != -ENOSPC)
return retval; <- このブロック内で書き込めたら終了
・・・・・・・
}
書き込めなかったので新規ブロックを獲得
bh = ext3_append(handle, dir, &block, &retval);
・・・・・・・
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
ext3_appendでまず、次のブロックを作成モードext3_breadの3番目の引数が1で呼び出され、ブロックが確保しているようです。そしてinode->i_sizeにスーパブロックサイズを足しこんでいるようです。
static struct buffer_head *ext3_append(handle_t *handle,
struct inode *inode,
u32 *block, int *err)
{
struct buffer_head *bh;
*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
bh = ext3_bread(handle, inode, *block, 1, err);
if (bh) {
inode->i_size += inode->i_sb->s_blocksize; <-スーパブロックのサイズ増
EXT3_I(inode)->i_disksize = inode->i_size;
*err = ext3_journal_get_write_access(handle, bh);
if (*err) {
brelse(bh);
bh = NULL;
}
}
return bh;
}
結論としてディレクトリサイズは、スパーブロックサイズ単位で増えていくようです。p/s
inodeのディレクトリ構造からみて、ディレクトリサイズは意味がない。
下記はディレクトリエントリの構造のイメージである。
inode1,rec_len1,name_len1,file_type1,name1 inode2,rec_len2,name_len2,file2_type2,name2name2を削除する場合、name1のエントリーのrec_len1に削除するrec_len2を足しこむことで実現していてる。従ってディレクトリのサイズは意味ないと言える。




