NFSとsuper_blockについて(Apple ペンシルで描いた図解)

前回さらっとsuper_blockからnfsの情報を取得する方法を記述しました。
もしかしたら、「え???」と思う方がいるかもしれないので、
図を使って説明したいと思います。 せっかくApple ペンシルを買ったので、練習したいというのが、ホントの理由です。

まずは、ざっくり3つの領域を説明したいと思います。
1. ユーザー空間
アプリケーション(OS上で動作するソフトウェア)が使用するメモリ領域

2. カーネル空間
カーネルが使用するメモリ領域

3. ハードウェア
ハードディスクなど

図にするとこのような感じになります。
f:id:shinji629:20181210113816j:plain
ここでポイントとなるのは、VFSNFSの関係性です。Virtual FileSystem(VFS)は、ファイルシステムExt4NFSなど)の上位に位置する抽象化層です。なぜ抽象化するかといえば、ファイルシステムの違いを意識することなくアクセスが可能になるからです。

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の情報を取得することができます。