crashコマンドの使い方(file_systems編)
以前super_blockからNFS情報を取得する方法を書きました。
Linuxではさまざまな種類のファイルシステムを扱うことができ、それぞれのオブジェクトが必要となります。このオブジェクトがfile_system_typeという構造体であり、file_systemsというグローバル変数です。
そこで今回は、file_systemsからどんな情報が取れるかcrashコマンドを使って説明したいと思います。
初めに、file_systemsから、file_system_typeの一覧を表示してみます。手順は、listコマンドを使ってfile_system_type.nextを順番に辿っていきます。
crash> p file_systems file_systems = $1 = (struct file_system_type *) 0xffffffff819f95c0 <sysfs_fs_type> crash> struct -o file_system_type struct file_system_type { [0x0] const char *name; [0x8] int fs_flags; struct dentry *(*mount)(struct file_system_type *, int, const char *, void *); [0x18] void (*kill_sb)(struct super_block *); [0x20] struct module *owner; [0x28] struct file_system_type *next; ... crash> list file_system_type.next 0xffffffff819f95c0 -s file_system_type.name ffffffff819f95c0 name = 0xffffffff818b3596 "sysfs" ffffffff819fa000 name = 0xffffffff81897bf5 "rootfs" ... name = 0xffffffffa026a1c4 "xfs" ffffffffa0331b80 name = 0xffffffffa0328be0 "rpc_pipefs" ffffffffa03839c0 name = 0xffffffffa037fae0 "nfsd" ffffffffa05ea1e0 name = 0xffffffffa05e4e47 "nfs" ffffffffa05ea160 name = 0xffffffffa05e4e42 "nfs4" crash>
ここでは、nfs4を例にして、file_system_typeの値を表示してみます。
crash> file_system_type 0xffffffffa05ea160 struct file_system_type { name = 0xffffffffa05e4e42 "nfs4", fs_flags = 0x8002, mount = 0xffffffffa05ce030 <nfs_fs_mount>, kill_sb = 0xffffffffa05cd870 <nfs_kill_super>, owner = 0xffffffffa05edbe0 <__this_module>, next = 0x0, fs_supers = { first = 0xffff880035a83138 }, ... }
file_system_typeの構造体を確認すると、fs_supersは次のように定義されています。
include/linux/fs.h: ... struct file_system_type { const char *name; int fs_flags; ... struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct hlist_head fs_supers;
また、hlist_headが何かを確認し、hlist_nodeの値も取得してみます。
crash> whatis hlist_head struct hlist_head { struct hlist_node *first; } SIZE: 0x8 crash> whatis hlist_node struct hlist_node { struct hlist_node *next; struct hlist_node **pprev; } SIZE: 0x10 crash> hlist_node 0xffff880035a83138 struct hlist_node { next = 0x0, pprev = 0xffffffffa05ea190 <nfs4_fs_type+48> }
このfs_supersは、super_blockのs_instancesに登録されているので、super_blockを参照しても確認できます。
fs/super.c: ... struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), int flags, void *data) { struct super_block *s = NULL; ... s->s_type = type; strlcpy(s->s_id, type->name, sizeof(s->s_id)); list_add_tail(&s->s_list, &super_blocks); hlist_add_head(&s->s_instances, &type->fs_supers);
では、マウントされている状況で確認してみます。
crash> mount MOUNT SUPERBLK TYPE DEVNAME DIRNAME ffff88007d12e100 ffff88007c771000 rootfs rootfs / ffff88007ac57700 ffff88007c220800 sysfs sysfs /sys ... ffff88007b817200 ffff880035a83000 nfs4 192.168.122.135:/tmp /mnt crash> crash> super_block ffff880035a83000 struct super_block { s_list = { next = 0xffffffff819ea610 <super_blocks>, prev = 0xffff8800799d1000 }, ... s_mtd = 0x0, s_instances = { next = 0x0, pprev = 0xffffffffa05ea190 },
file_system_typeのfs_supersでもsuper_blockのs_instancesでも「0xffffffffa05ea190」が確認できたので、繋がりがあることがわかります。
図にすると、このような関係性になります。