TenForward

技術ブログ。はてなダイアリーから移転しました

マウントプロパゲーション(1)〜 shared mount 〜

完全に私個人が理解するための資料です。間違いの指摘は大歓迎です。

2001 年に 2.4 kernel でバインド(bind)マウントが、2002 年の 2.4.19 で mount namespace が導入されました。ただ、ユースケースによっては mount namespace が行う分離は徹底しているので、もう少しマウントが共有されても良いシーンがあったようで、shared マウントなどのマウントプロパゲーションの考え方が 2.6.15(2006 年 1 月)で導入されました。

そのマウントプロパゲーションについてまとめていきます。

説明中の「サブマウント」とは、あるマウントポイントがあったとして、そのツリー配下で行われるマウント処理のことを指すとします。例えば、ホストで/dev/sda1というデバイスをルート/にマウントします。その配下の/home/dev/sda2をマウントしたりしますが、この/homeをサブマウントと呼ぶことにします。

プロパゲーションの設定 説明
shared マウント元のサブマウントはマウント先にも反映される。マウント先配下のサブマウントはマウント元にも反映される
private あるマウント配下でのサブマウントは他のマウント配下には公開されない
slave マウント元のサブマウントはマウント先にも反映されるが、マウント先のサブマウントはマウント元には反映されない
unbindable privateと同様でさらにこのマウントをバインドマウントできない

上のそれぞれについて、配下のマウントに再帰的に設定を反映させることができます。

プロパゲーションの設定 説明
rshared 配下で行われるマウントすべてを shared にする
rprivate 配下で行われるマウントすべてを private にする
rslave 配下で行われるマウントすべてを slave にする
runbindable 配下で行われるマウントすべてを unbindable にする

では、バインドマウントを使ってマウントプロパゲーションの説明をしていきましょう。

shared

まずはsharedです。sharedは、複数のマウント配下で行ったマウントがお互いに伝播します。

まず、バインドマウント用にorigbindというディレクトリをふたつ作ります。そしてバインドマウントを行います。バインドマウント元ディレクトorig内にtmpというディレクトリを作りました。

# mkdir orig bind
# mount --bind orig bind (origをbindにバインドマウント)
# mkdir orig/tmp (orig内にtmpというディレクトリを作成)

origbindにもバインドマウントされているので、次のように両方のディレクトリにtmpディレクトリが見えます。

# tree .
.
├── bind
│   └── tmp
└── orig
    └── tmp

4 directories, 0 files

ここでbindをsharedマウントとしてみましょう。sharedにするにはmountコマンドに--make-sharedを指定します。

# mount --make-shared bind
# grep bind /proc/self/mountinfo (マウント情報の確認)
518 30 253:0 /root/test/orig /root/test/bind rw,relatime shared:1 - ext4 /dev/mapper/ubuntu--vg-ubuntu--lv rw
(shared指定されている)

sharedになっていることを確認するために/proc/self/mountinfoを確認したところ、きちんと"shared"という文字がみえます。ここでshared指定されたbind以下でマウント操作を行ってみます。ここではtmpディレクトリにtmpfsをマウントしてみましょう。

# mount -t tmpfs tmpfs bind/tmp (bind以下のtmpにtmpfsマウント)
# egrep "bind.*tmpfs" /proc/self/mountinfo (マウントされたのを確認)
546 518 0:49 / /root/test/bind/tmp rw,relatime shared:253 - tmpfs tmpfs rw

tmpfsがマウントされていますので、このtmpfs上にファイルを置いてみましょう。そしてorigbindの配下がどうなっているのかを確認してみます。

# touch bind/tmp/testfile (tmpfs上にファイルを置く)
# tree .
.
├── bind
│   └── tmp
│       └── testfile
└── orig
    └── tmp
        └── testfile

4 directories, 2 files

バインドマウント先のbind内でマウントしたtmpfsがバインドマウント元でもマウントされた状態になっています。

この逆もやってみましょう。origディレクトリはマウントポイントではありませんので、ここではorigディレクトリが所属するマウントのマウントポイントであるルート(/)でsharedを指定します。ここは環境によって違いますので、実際に試す場合は適宜変更してください。

# mount --make-shared /

そしてorigディレクトリ以下にtmp2ディレクトリを作成しtmpfsをマウントし、ファイルを置きます。

# mkdir orig/tmp2
# mount -t tmpfs tmpfs orig/tmp2/ (tmp2にtmpfsをマウント)
# touch orig/tmp2/testfile2 (tmpfs上にファイルを置く)
# tree .
.
├── bind
│   ├── tmp
│   │   └── testfile
│   └── tmp2
│       └── testfile2
└── orig
    ├── tmp
    │   └── testfile
    └── tmp2
        └── testfile2

6 directories, 4 files

上のように、orig以下で行ったマウントがきちんとbind以下でも見えています。

このようにsharedに設定したマウント配下で行ったマウントは、他のマウント配下にも反映されます。