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」が確認できたので、繋がりがあることがわかります。
図にすると、このような関係性になります。
