メモ
何か色々な意味でとっちらかっててメモにさえなっとらん。スデに控えてるかもしれない部分含め以下に。
とりあえず
statfs がどの属性を使ってるかを控えてない模様。ええと sys_statfs() の定義は fs/open.c にて以下。
asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) { struct nameidata nd; int error; error = user_path_walk(path, &nd); if (!error) { struct statfs tmp; error = vfs_statfs_native(nd.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); } return error; }
vfs_statfs_native() を掘ってみる。同様に fs/open.c にて以下に一部のみ。
static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) { struct kstatfs st; int retval; retval = vfs_statfs(dentry, &st); if (retval) return retval;
この後、st 側から buf 側にコピーする処理が書いてある。vfs_statfs() な戻りは 0 が normal なので上記末端は不具合時の分岐になるのか。
ちなみに以下が肝心な部分と思われる。man statfs によれば f_blocks 属性が_ファイルシステムの総ブロック数_との事。
buf->f_bsize = st.f_bsize; buf->f_blocks = st.f_blocks;
次に vfs_statfs() を掘ってみると定義は同様に fs/open.c で以下。
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) { int retval = -ENODEV; if (dentry) { retval = -ENOSYS; if (dentry->d_sb->s_op->statfs) { memset(buf, 0, sizeof(*buf)); retval = security_sb_statfs(dentry); if (retval) return retval; retval = dentry->d_sb->s_op->statfs(dentry, buf); if (retval == 0 && buf->f_frsize == 0) buf->f_frsize = buf->f_bsize; } } return retval; }
タブが微妙ですがご勘弁下さい。結局ファイルシステムの statfs 属性が呼ばれる模様。ext3 の struct super_operations の statfs 属性には ext3_statfs() な関数ポインタが設定されている。
という事で fs/ext3/super.c を見てみると、簡単に考えてたんですが理解が全然だった事が判明。ってか、s_blocksize がソレにあたる、という大誤読あり。あり得ん。
とりあえず核心は以下みたいなんですが
buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
このあたりもう少しきっちり確認必要。先頭から。
static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) { struct super_block *sb = dentry->d_sb; struct ext3_sb_info *sbi = EXT3_SB(sb); struct ext3_super_block *es = sbi->s_es; ext3_fsblk_t overhead; int i; u64 fsid;
引数で頂いた struct dentry な領域の d_sb 属性を super block として取り出して EXT3_SB というマクロでファイルシステム固有のデータが格納される s_fs_info 属性を取り出している模様。定義が以下のはず。
static inline struct ext3_sb_info * EXT3_SB(struct super_block *sb) { return sb->s_fs_info; }
で、struct ext3_sb_info 構造体なメンバの s_es を取り出している。属性定義は以下な模様 (include/linux/ext3_fs_sb.h)。
struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
で、この ext3_super_block な s_blocks_count 属性がそれにあたる、と。ただ、処理にあたって overhead を引いた値を f_blocks 属性に格納してますな。とりあえず overhead の準備を確認。
if (test_opt (sb, MINIX_DF)) overhead = 0; else {
な分岐あり。test_opt はマクロで include/linux/ext3_fs.h にて定義。
#define test_opt(sb, opt) (EXT3_SB(sb)->s_mount_opt & \ EXT3_MOUNT_##opt)
これどう展開されるか、というと以下なカンジ?
if (EXT3_SB(sb)->s_mount_opt & EXT3_MOUNT_MINIX_DF)
EXT3_MOUNT_MINIX_DF は直上で定義されてて以下。
#define EXT3_MOUNT_MINIX_DF 0x00080 /* Mimics the Minix statfs */
struct ext3_sb_info の s_mount_opt 属性って_マウントオプション_となっている。ここのビットが立ってたら overhead は 0 なのか。とりあえず細かいナニは一旦スルーで s_blocks_count で grep してみるか。このあたり、別途色々確認予定です。