vfsmountの検証
vfsmount構造体のパスリンクに掛かる情報は以下のとうりで、実際この内容を検証してみました。
struct vfsmount { struct dentry *mnt_root; /* root of the mounted tree */ : }; struct mount { struct mount *mnt_parent; struct dentry *mnt_mountpoint; struct vfsmount mnt; const char *mnt_devname; : };/tmp/hoge0に/dev/loop0をマウントし、/tmp/hoge0/hoge1に/dev/loop1をマウントした状態の/dev/loop1のvfsmount構造体の内容です。
[root@localhost lkm]# mount /home/kitamura/lkm/disk/disk0 on /tmp/hoge0 type ext2 /home/kitamura/lkm/disk/disk1 on /tmp/hoge0/hoge1 type ext2
#include <linux/kernel.h> #include <linux/namei.h> #include <linux/mnt_namespace.h> #include <linux/mount.h> struct mount { struct list_head mnt_hash; struct mount *mnt_parent; struct dentry *mnt_mountpoint; struct vfsmount mnt; int mnt_count; int mnt_writers; struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ struct list_head mnt_instance; /* mount instance on sb->s_mounts */ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct list_head mnt_share; /* circular list of shared mounts */ struct list_head mnt_slave_list;/* list of slave mounts */ struct list_head mnt_slave; /* slave list entry */ struct mount *mnt_master; /* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns; /* containing namespace */ int mnt_id; /* mount identifier */ int mnt_group_id; /* peer group identifier */ int mnt_expiry_mark; /* true if marked for expiry */ int mnt_pinned; int mnt_ghosts; }; static inline struct mount *real_mount(struct vfsmount *mnt) { return container_of(mnt, struct mount, mnt); } void get_mntchild(struct mount *r_mnt) { struct mount *i; int act = 0; list_for_each_entry(i, &r_mnt->mnt_mounts, mnt_child) { act = 1; printk("child:%s\n", i->mnt_devname); } if (act == 0) { printk("child:no\n"); } } void get_mntinfo(char *pathname) { struct path path; struct mount *r_mnt; int err; printk("%s\n", pathname); err = kern_path(pathname, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); if (err) { printk("err\n"); } else { r_mnt = real_mount(path.mnt); printk("devname:%s\n",r_mnt->mnt_devname); printk("root:%s\n", path.mnt->mnt_root->d_name.name); printk("parent:%s\n",r_mnt->mnt_parent->mnt_devname); printk("mountpoint:%s\n",r_mnt->mnt_mountpoint->d_name.name); get_mntchild(r_mnt); printk("----------\n"); path_put(&path); } } int init_module(void) { get_mntinfo("/tmp/hoge0"); get_mntinfo("/tmp/hoge0/hoge1"); return 0; } void cleanup_module(void) { }期待通りの結果となりました。
[root@localhost lkm]# dmesg : [39913.089605] /tmp/hoge0 [39913.089629] devname:/dev/loop0 [39913.089634] root:/ <- [39913.089639] parent:/dev/mapper/VolGroup-lv_root [39913.089644] mountpoint:hoge0 [39913.089649] child:/dev/loop1 [39913.089652] ---------- [39913.089657] /tmp/hoge0/hoge1 [39913.089665] devname:/dev/loop1 [39913.089670] root:/ [39913.089673] parent:/dev/loop0 [39913.089677] mountpoint:hoge1 [39913.089681] child:noroot:はmountのマウント元で、bindオプションによって変わります。