vfsmountのリスト管理の検証(その1)


システム下のマウントのリスト管理では、vfsmount構造体のstruct list_headのmnt_mounts/mnt_child/mnt_hashの3つのメンバーが重要な役割を担っています。mnt_mountはその配下にマウントされている、ファイルシステムのリストのヘッドとなり、配下のファイルシステムはmnt_childをノードとしてリストされていきます。ここではまずmnt_mounts/mnt_childについてです。

以下のサンプルは、ルートファイルシステムをヘッドとして、mnt_mounts/mnt_childの関係を検証するものです。始めのループバックのマウントは上の検証結果をわかりやすくするためのものです。
[root@localhost kitamura]# mkdir /mnt/mntpoint1
[root@localhost kitamura]# mkdir /mnt/mntpoint2
[root@localhost kitamura]# mkdir /mnt/mntpoint3
[root@localhost kitamura]# mkdir /mnt/mntpoint1/mntpoint11
[root@localhost kitamura]# mkdir /mnt/mntpoint1/mntpoint12
[root@localhost kitamura]# mkdir /mnt/mntpoint1/mntpoint13
[root@localhost kitamura]# mkdir /mnt/mntpoint2/mntpoint21
[root@localhost kitamura]# mkdir /mnt/mntpoint2/mntpoint22
[root@localhost kitamura]# mount disk /mnt/mntpoint1
[root@localhost kitamura]# mount disk /mnt/mntpoint2
[root@localhost kitamura]# mount disk /mnt/mntpoint3
[root@localhost kitamura]# mount disk /mnt/mntpoint1/mntpoint11
[root@localhost kitamura]# mount disk /mnt/mntpoint1/mntpoint12
[root@localhost kitamura]# mount disk /mnt/mntpoint1/mntpoint13
[root@localhost kitamura]# mount disk /mnt/mntpoint1/mntpoint21
[root@localhost kitamura]# mount disk /mnt/mntpoint2/mntpoint22
[root@localhost kitamura]# insmod testmod.ko
[root@localhost kitamura]# dmesg
   :
   :
[ 4316.028006] selinux
[ 4316.028446] dev
[ 4316.028672]   /
[ 4316.028819]     pts
[ 4316.028860]     shm
[ 4316.029077] proc
[ 4316.029093]   usb
[ 4316.029111]   binfmt_misc
[ 4316.029131] sys
[ 4316.029143] boot
[ 4316.029568] rpc_pipefs
[ 4316.029587] mntpoint1
[ 4316.029600]   mntpoint11
[ 4316.029617]   mntpoint12
[ 4316.029634]   mntpoint13
[ 4316.029653] mntpoint2
[ 4316.029666]   mntpoint21
[ 4316.029683]   mntpoint22
[ 4316.029702] mntpoint3
path_lookup()でルートファイルシステムのvfsmountを取得し、get_mntinfo()をコールします。なおこの関数は再帰処理となっています。

get_mntinfo()では、まずは以下のファイルシステムをリストしているヘッドを取得し、それにリストされているvfsmountを求めるだけです。なおこれにリストされているノードは、mnt_mountsでなくmnt_childという事です。mnt_childが見つかる毎に、それでもっとget_mntinfo()をコールするだけです。mnt_child->nextがトップと同じなら、一巡したと言うことで、それ以上ノードはないと言うことです。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/kernel.h>
#include <linux/dcache.h>
#include <linux/mnt_namespace.h>
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/fcntl.h>
#include <linux/list.h>
#include <linux/fs.h>

MODULE_LICENSE("GPL");

static int get_mntinfo(struct vfsmount  *mnt, int depth);
static void prn_space(int space);

static int test_init(void)
{
   struct nameidata nd;

   int err = path_lookup("/", LOOKUP_FOLLOW, &nd);
   if (err) {
       printk("path_look err.\n");
       return -1;
   }
   get_mntinfo(nd.path.mnt, 0);
   return 0;
}

static int get_mntinfo(struct vfsmount  *mnt, int depth)
{
   struct vfsmount  *mnt_child;
   sruct list_head *p, *head;

   p = head = &mnt->mnt_mounts;
   p = p->next;
   for (;;) {
       mnt_child = list_entry(p, struct vfsmount, mnt_child);
	prn_space(depth);
	printk("%s\n", mnt_child->mnt_mountpoint->d_name.name);
       if(mnt_child->mnt_mounts.next != &mnt_child->mnt_mounts) {
           depth = get_mntinfo(mnt_child, ++depth);
       }
       p = p->next;
       if (head == p)
  	    break;
   }
   return --depth;
}

static void prn_space(int space)
{
   int	i;
   for(i = 0; i < space; i++) {
       printk("  ");
   }
}

static void test_exit(void)
{
}

module_init(test_init);
module_exit(test_exit);
ディレクトリを検索で、マウントされているディレクトリに遭遇すると、このようにファイルシステム配下の子ファイルシステムのマウントポイントを調べる事で、マウントされたのディレクトリを渡って行くことができそうです。

しかし、そのような実装にはなっていません。もし上記の実装だと、配下の全子プロセスをチェックする必要があります。また、mountのmountと言った機能が実現できません。mnt_mounts/mnt_childではマウント順序という管理ができていないからです。そこで参照されるのがmnt_hashになります。


最終更新 2012/01/22 16:50:04 - north
(2012/01/22 16:50:04 作成)


検索

アクセス数
3689183
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。