マウントプロパゲーション(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は、複数のマウント配下で行ったマウントがお互いに伝播します。
まず、バインドマウント用にorig
とbind
というディレクトリをふたつ作ります。そしてバインドマウントを行います。バインドマウント元ディレクトリorig
内にtmp
というディレクトリを作りました。
# mkdir orig bind # mount --bind orig bind (origをbindにバインドマウント) # mkdir orig/tmp (orig内にtmpというディレクトリを作成)
orig
がbind
にもバインドマウントされているので、次のように両方のディレクトリに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上にファイルを置いてみましょう。そしてorig
とbind
の配下がどうなっているのかを確認してみます。
# 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に設定したマウント配下で行ったマウントは、他のマウント配下にも反映されます。