fast_symlink
Rev.1を表示中。最新版はこちら。
lsコマンドの表示について(ディレクトリのサイズ)というのがあった。新規に作成したディレクトリのサイズが4096の倍数で表示されるというものだ。実際新規にディレクトリを作成してls -lとしてみると、確かに4096で、その下にファイルを作成しても4096のままである。Takeshi Kusune さんが実装にもとずいて説明されている。ディレクトリもファイルと同じ扱いをする。ファイル同じようにiノードをもつ。(ただし、file_operetion,inode_operatinのコールバック関数は異なる。)そしてファイルと同じようにデータブロックをもつ。ディレクトリはこのデータブロックに配下のファイルのiノードとファイル名を記述しており、ファイルと同じように実際のサイズを有している。しかし考えてみればディレクトリのサイズは意味がない。ユーザがそれを読み書きするような事はないからだ。
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だ。
配下にファイルをどんどん作成していって、4096を超えた場合別のデータブロックを使うことになる。その場合のサイズは4096*2となるか? ソースを追ってみたが追えきれず。
しかし別に副産物を発見。以前からinode_operationでsymlinkとfast_symlinkというものが何が異なるのか不思議に思っていた。
fs/ext3/namei.cのstatic int ext3_symlink (struct inode * dir, struct dentry *dentry, const char * symname)で
if (l > sizeof (EXT3_I(inode)->i_data)) { inode->i_op = &ext3_symlink_inode_operations; ext3_set_aops(inode); err = __page_symlink(inode, symname, l, 1); if (err) { drop_nlink(inode); ext3_mark_inode_dirty(handle, inode); iput (inode); goto out_stop; } } else { inode->i_op = &ext3_fast_symlink_inode_operations; memcpy((char*)&EXT3_I(inode)->i_data,symname,l); inode->i_size = l-1; }
ext2/3ファイルのシンボリック名はiノードのあるサイズ以下であれば直接iノードに設定され、そうでないならデータブロックを使用するというのは前知識としてあった。それがメモリーiノードについても同じような処理がされている。lはシンボリック名のサイズである。i_dataはメモリーiノードのデータブロックのようなものだ。もしそれがi_dataサイズより大きければsymlinkを、そうでなければi_data領域にシンボル名を設定し、その処理関数がfast_symlinkとなるようだ。