無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

SLAVEマウント


mount --bind mnt1 mnt2は、mnt1がSHAREなら、mnt1.mnt_shareにmnt2がリストされ、mnt1がSLAVEなら、mnt1.mnt_slaveにmnt2がリストされ、mnt2.mnt_master = mnt1.mnt_masterとなります。mnt1がクーロンmntでないならmnt1.mnt_master=mnt1で、mountのdentryのmnt.mnt_masterからmnt_shareリストのmntにもmountされます。

make-slaveするとmnt_shareにリストされているmntが削除され、mnt.mnt_master=mntとなり、従ってmnt1をSLAVEすると、全BINDしてるmntは無効となり、mnt2をSLAVすると、mnt2.mnt_masteからのmnt1.mnt_shareへ参照できず、mnt1へはmountされなくなります。
static int do_make_slave(struct mount *mnt)
{
       struct mount *peer_mnt = mnt, *master = mnt->mnt_master;
       struct mount *slave_mnt;

       while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
              peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ;

       if (peer_mnt == mnt) {
               peer_mnt = next_peer(mnt);
               if (peer_mnt == mnt)
                       peer_mnt = NULL;
       }
       if (IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share))
               mnt_release_group_id(mnt);

       list_del_init(&mnt->mnt_share);
       mnt->mnt_group_id = 0;

       if (peer_mnt)
               master = peer_mnt;

       if (master) {
               list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
                       slave_mnt->mnt_master = master;
               list_move(&mnt->mnt_slave, &master->mnt_slave_list);
               list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
               INIT_LIST_HEAD(&mnt->mnt_slave_list);
       } else {
               struct list_head *p = &mnt->mnt_slave_list;
               while (!list_empty(p)) {
                       slave_mnt = list_first_entry(p,
                                       struct mount, mnt_slave);
                       list_del_init(&slave_mnt->mnt_slave);
                       slave_mnt->mnt_master = NULL;
               }
       }
       mnt->mnt_master = master;
       CLEAR_MNT_SHARED(mnt);
       return 0;
}

クーロンmnt2をSLAVE: クーロンmnt1ソースへのmntは全クーロンmntに反映されます

[root@localhost loop]# mount --make-shared mnt1
[root@localhost loop]# mount --bind mnt1 mnt2
[root@localhost loop]# mount --bind mnt1 mnt3
[root@localhost loop]# mount --make-slave mnt2
[root@localhost loop]# mount -o loop loopfile4 mnt1

[root@localhost loop]# ls mnt1
lost+found  mnt4.txt
[root@localhost loop]# ls mnt2
lost+found  mnt4.txt  
[root@localhost loop]# ls mnt3
lost+found  mnt4.txt

クーロンmnt2をSLAVE: クーロンmnt2へのmntはクーロンmnt1ソース及び他のSLAVE mntに反映されません。

[root@localhost loop]# mount --make-shared mnt1
[root@localhost loop]# mount --bind mnt1 mnt2
[root@localhost loop]# mount --bind mnt1 mnt3
[root@localhost loop]# mount --make-slave mnt2
[root@localhost loop]# mount -o loop loopfile4 mnt2

[root@localhost loop]# ls mnt1
lost+found  mnt1.txt 
[root@localhost loop]# ls mnt2
lost+found  mnt4.txt 
[root@localhost loop]# ls mnt3
lost+found  mnt1.txt 

[root@localhost loop]# mount --make-shared mnt1
[root@localhost loop]# mount --bind mnt1 mnt2
[root@localhost loop]# mount --bind mnt1 mnt3
[root@localhost loop]# mount --make-slave mnt2
[root@localhost loop]# mount -o loop loopfile4 mnt3

[root@localhost loop]# ls mnt1
lost+found  mnt4.txt 
[root@localhost loop]# ls mnt2
lost+found  mnt4.txt 
[root@localhost loop]# ls mnt3
lost+found  mnt4.txt 

クーロンmnt1ソースをSLAVE: mnt1をソースとする他の全SLAVE mntに反映されません。

[root@localhost loop]# mount --make-shared mnt1
[root@localhost loop]# mount --bind mnt1 mnt2
[root@localhost loop]# mount --bind mnt1 mnt3
[root@localhost loop]# mount --make-slave mnt1
[root@localhost loop]# mount -o loop loopfile4 mnt1

[root@localhost loop]# ls mnt1
lost+found  mnt4.txt 
[root@localhost loop]# ls mnt2
lost+found  mnt1.txt 
[root@localhost loop]# ls mnt3
lost+found  mnt1.txt 

補足

mount bindのdo_loopback()からpropagate_mnt()がコールされ、mount対象となるmntをtree_listにリストします。

mntのmnt_shareにリストされているmntのmnt_shareにリストmntと階層的に反映していきますが、この時階層化のmnt_slaveも対象となります。(SLAVEでbindし、--make-shareで共有mntした後、それでrbindすると、先のSLAVEでbindしたmntも対象となります。--make-shareは((m)->mnt.mnt_flags & MNT_SHARED)とするだけで、--make-slaveと異なり掛かるbindリスト情報の変更はありません。
int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
                   struct mount *source_mnt, struct list_head *tree_list)
{
       struct mount *m, *child;
       int ret = 0;
       struct mount *prev_dest_mnt = dest_mnt;
       struct mount *prev_src_mnt  = source_mnt;
       LIST_HEAD(tmp_list);
       LIST_HEAD(umount_list);

       for (m = propagation_next(dest_mnt, dest_mnt); m;
                       m = propagation_next(m, dest_mnt)) {
               int type;
               struct mount *source;

               if (IS_MNT_NEW(m))
                       continue;

               source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);

               if (!(child = copy_tree(source, source->mnt.mnt_root, type))) {
                       ret = -ENOMEM;
                       list_splice(tree_list, tmp_list.prev);
                       goto out;
               }

               if (is_subdir(dest_dentry, m->mnt.mnt_root)) {
                       mnt_set_mountpoint(m, dest_dentry, child);
                       list_add_tail(&child->mnt_hash, tree_list);
               } else {
                       list_add_tail(&child->mnt_hash, &tmp_list);
               }
               prev_dest_mnt = m;
               prev_src_mnt  = child;
       }
out:
       br_write_lock(vfsmount_lock);
       while (!list_empty(&tmp_list)) {
               child = list_first_entry(&tmp_list, struct mount, mnt_hash);
               umount_tree(child, 0, &umount_list);
       }
       br_write_unlock(vfsmount_lock);
       release_mounts(&umount_list);
       return ret;
}

static struct mount *propagation_next(struct mount *m,
                                        struct mount *origin)
{ 
       while (1) {
               struct mount *master = m->mnt_master;

               if (master == origin->mnt_master) {
                       struct mount *next = next_peer(m);
                       return (next == origin) ? NULL : next;
               } else if (m->mnt_slave.next != &master->mnt_slave_list)
                       return next_slave(m);

               m = master;
       }
}

static inline struct mount *next_peer(struct mount *p)
{
       return list_entry(p->mnt_share.next, struct mount, mnt_share);
}

static inline struct mount *next_slave(struct mount *p)
{
       return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
}

最終更新 2016/06/29 19:58:22 - north
(2016/06/29 19:49:17 作成)