NFSとsuper_blockについて(Apple ペンシルで描いた図解)
前回さらっとsuper_blockからnfsの情報を取得する方法を記述しました。
もしかしたら、「え???」と思う方がいるかもしれないので、
図を使って説明したいと思います。 せっかくApple ペンシルを買ったので、練習したいというのが、ホントの理由です。
まずは、ざっくり3つの領域を説明したいと思います。
1. ユーザー空間
アプリケーション(OS上で動作するソフトウェア)が使用するメモリ領域
3. ハードウェア
ハードディスクなど
図にするとこのような感じになります。
ここでポイントとなるのは、VFSとNFSの関係性です。Virtual FileSystem(VFS)は、ファイルシステム(Ext4やNFSなど)の上位に位置する抽象化層です。なぜ抽象化するかといえば、ファイルシステムの違いを意識することなくアクセスが可能になるからです。
VFSを構成する主な4つのオブジェクトがこちらです。
- superblock: マウントされたファイルシステムに関する情報
- inode: ファイルに関する情報
- file: プロセスによってオープンされたファイルに関する情報
- dentry: ディレクトリエントリ(パス)に関する情報
マウントされたローカルファイルシステムに対する情報は、super_blockに登録されています。では、早速super_blockのデータ構造を見ていきましょう。
include/linux/fs.h ... struct super_block { struct list_head s_list; /* Keep this first */ dev_t s_dev; /* search index; _not_ kdev_t */ unsigned char s_blocksize_bits; unsigned long s_blocksize; loff_t s_maxbytes; /* Max file size */ struct file_system_type *s_type; const struct super_operations *s_op; const struct dquot_operations *dq_op; ...
s_typeをチェックして、ファイルシステムがNFSかどうか確認できます。例えば、グローバル変数のsuper_blocksのリンクリストからnfsのsuper_blockを探すこともできます。
crash> cat ~/macro/print-sb define print-superblocks set $n = super_blocks.next while ($n != &super_blocks) set $off = (unsigned long)&((struct super_block *)0)->s_list set $s = (struct super_block *)((unsigned long)$n - (unsigned long)$off) if ($s->s_type == &nfs_fs_type) printf "(struct super_block *) %p, type=nfs_fs_type\n", $s end if ($s->s_type == &nfs4_fs_type) printf "(struct super_block *) %p, type=nfs4_fs_type\n", $s end set $n = $n->next end end crash> source ~/macro/print-sb Redefine command "print-superblocks"? (y or n) [answered Y; input not from terminal] crash> print-superblocks (struct super_block *) 0xffff880035a83000, type=nfs4_fs_type
また、super_blockのメンバーのs_fs_infoにファイルシステムのプライベート情報が登録されます。NFSのサーバやクライアントの情報は、こちらで登録されます。
fs/nfs/super.c: ... static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags) { const struct nfs_server *a = s->s_fs_info; const struct rpc_clnt *clnt_a = a->client; const struct rpc_clnt *clnt_b = b->client; ...
この辺りの関係性が理解できると、vmcoreのsuper_blockからnfsの情報を取得することができます。