unshare -m とか mount --make-shared とか

`mount --make-shared` を始めとした `mount --make-XXX` なコマンドを試してみました。

なお、ほとんど下記の RHEL のドキュメントを参考・・というかそのまま試しています。

- [Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/sect-Using_the_mount_Command-Mounting.html](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/sect-Using_the_mount_Command-Mounting.html#sect-Using_the_mount_Command-Mounting-Bind)

次の環境で試しています。

- CentOS 7.2.1511 / kernel 3.10.0-327.el7.x86_64

また、すべて最初に `unshare -m` してから試しています（いちいちマウント解除するのが面倒だったから）。ので、最後の方にも書いていますが、`/` がデフォで shared にはなっていません。CentOS 7.2 だと普通は `/` がデフォで shared なので `unshare -m` せずに試すと異なる結果になります。

## mount --bind

次のようにすると、`/usr` の中身が `/mnt` でも見えるようになります。

```sh
mount --bind /usr /mnt
```

例えば `/usr/bin` と `/mnt/bin` が同じ内容になります。

```sh
ls /usr/bin
ls /mnt/bin
```

マウント元とマウント先のファイルシステムが同じである必要はないので、次のようにファイルシステムの種類を超えてマウントすることも可能です。

```sh
mount --bind /proc/$$ /mnt
```

わたしは cifs でマウントしたディレクトリの中を部分的にローカルにするためによく使ってます。

- [cifs でマウントした先の一部ディレクトリを mount --bind](http://ngyuki.hatenablog.com/entry/2013/08/26/182853)

## mount --rbind

`mount --bind` はマウント元のディレクトリの中にマウントされているファイルシステムには適用されないため、例えば次のようにマウントしても `/mnt/proc/` の中になにもありません。

```sh
mount --bind / /mnt
ll /mnt/proc/
# total 0
```

`mount --rbind` を使えばマウント元のディレクトリの中にマウントされているファイルシステムもマウント先に適用されます。

```sh
mount --rbind / /mnt
ll /mnt/proc/
# total 0
# dr-xr-xr-x.  9 root   root   0 May  7 03:44 1
# :
```

ちなみにこのマウントを解除するためには `-R` を指定して再帰的に解除する必要があります。

```sh
umount -R /mnt
```

## mount --make-shared

`mount --make-shared` でマウントポイントを共有マウントポイントにできます。

例えば、次のように `/media` を `/mnt` にマウントしたとします。

```sh
mount --bind /media /mnt
```

この後 `/media` の中に何かをマウントしたとしても `/mnt` には反映されません（後述の通り `unshare -m` しているためです、`unshare -m` していなければ、デフォで `/` は共有マウントポイントになっています）。

```sh
mkdir -p /media/foo
mount -t tmpfs tmpfs /media/foo
touch /media/foo/test

ll /media/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 02:57 test

ll /mnt/foo/
# total 0
```

しかし、次のように `/media` を共有マウントポイントにして、

```sh
mount --bind /media /media
mount --make-shared /media
```

`/media` を `/mnt` にマウントすると、

```sh
mount --bind /media /mnt
```

`/media` と `/mnt` でマウント情報が共有されるようになります。

```sh
mkdir -p /media/foo
mount -t tmpfs tmpfs /media/foo
touch /media/foo/test

ll /media/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:01 test

ll /mnt/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:01 test
```

また、逆に `/mnt` の中にマウントしたファイルシステムも、`/media` から見ることができます。

```sh
mkdir -p /mnt/bar
mount -t tmpfs tmpfs /mnt/bar
touch /mnt/bar/test

ll /mnt/bar
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:03 test

ll /media/bar
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:03 test
```

## mount --make-slave

共有マウントポイントをマウントしたとき、前述の通り、マウント元(`/media`)で行われたマウントも、マウント先(`/mnt`)で行われたマウントも両方とも共有されますが、マウント先で `mount --make-slave` すれば、マウント先で行われたマウントはマウント元に反映されないようにすることができます。

先ほどと同じように `/media` を共有マウントポイントにします。

```sh
mount --bind /media /media
mount --make-shared /media
```

`/media` を `/mnt` にマウントします。

```sh
mount --bind /media /mnt
```

このままだと `/mnt` の中にマウントしたファイルシステムが `/media` にも見えます。

次のようにマウント先のマウントポイントを `mount --make-slave` でスレーブマウントポイントにします。

```sh
mount --make-slave /mnt
```

すると、`/media` の中にマウントしたファイルシステムは `/mnt` にも反映されますが、その逆は反映されなくなります。


```sh
mkdir -p /media/foo
mkdir -p /mnt/bar
mount -t tmpfs tmpfs /media/foo
mount -t tmpfs tmpfs /mnt/bar
touch /media/foo/test
touch /mnt/bar/test

ll /media/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:11 test

ll /mnt/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:11 test

ll /mnt/bar
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:12 test

ll /media/bar
# total 0
```

## mount --make-private

`mount --make-private` でマウントポイントをプライベートにすることができます。

これがデフォルトです。なので `mount --make-shared` の説明で示した最初の例がプライベートなマウントポイントの動作です。つまり `/media` の中に作成したマウントポイントが `/mnt` の中に反映されることはありませんし、その逆もありません（と思ってたんですが、`unshare -m` していない場合は `/` がデフォで shared になっています）。

既に shared となっているマウントポイントをマウントしたときに、マウント先で private に設定することもできます。

例えば先ほどと同じように `/media` を共有マウントポイントにして `/mnt` にマウントして、

```sh
mount --bind /media /media
mount --make-shared /media
mount --bind /media /mnt
```

次のようにマウント先を private にします。

```sh
mount --make-private /mnt
```

すると、`/media` の中のマウントも `/mnt` の中のマウントも反映されなくなります。

```sh
mkdir -p /media/foo
mkdir -p /mnt/bar
mount -t tmpfs tmpfs /media/foo
mount -t tmpfs tmpfs /mnt/bar
touch /media/foo/test
touch /mnt/bar/test

ll /media/foo/
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:18 test

ll /mnt/foo/
# total 0

ll /mnt/bar
# total 0
# -rw-r--r--. 1 root root 0 May  7 03:19 test

ll /media/bar
# total 0
```

## mount --make-unbindable

`mount --make-unbindable` で、そのマウントポイントをバインド不可にすることができます。

例えば次のようにすると `/` やその中のディレクトリが `mount --bind` できなくなります。

```sh
mount --make-unbindable /

mount --bind / /mnt
# mount: wrong fs type, bad option, bad superblock on /,
#        missing codepage or helper program, or other error

mount --bind /media /mnt
# mount: wrong fs type, bad option, bad superblock on /media,
#        missing codepage or helper program, or other error
```

## mount --make-rshared|--make-rslave|--make-rprivate|--make-runbindable

`mount --make-XXX` はいずれも再帰的な効果はないため、例えば次のように `/` をバインド不可にしても、

```sh
mount --make-unbindable /
```

`/proc` のように別のマウントポイントには影響しません。

```sh
mount --bind /proc /mnt
ll /proc
# total 0
# dr-xr-xr-x.  9 root  root       0 May  7 02:33 1
 :
```

次のように `r` を付けると再帰的に適用されるため、`/proc` もバインド不可になります。

```sh
mount --make-runbindable /
mount --bind /proc /mnt
# mount: wrong fs type, bad option, bad superblock on /proc,
#        missing codepage or helper program, or other error
```

同様に shared/slave/private も再帰的に適用することができます。

```sh
mount --make-rshared /mnt
mount --make-rslave /mnt
mount --make-rprivate /mnt
```

## unshare -m と mount --make-private

下記の記事のようにディストリビューションによっては `/` がデフォで shared になっているらしく、`unshare -m` の後で `mount --make-private` しないとマウントが分離されないそうです。

- [マウント名前空間でちょっとハマっためも - φ(・・*)ゞ ｳｰﾝ　カーネルとか弄ったりのメモ](http://kernhack.hatenablog.com/entry/2015/05/30/115705 "マウント名前空間でちょっとハマっためも - φ(・・*)ゞ ｳｰﾝ　カーネルとか弄ったりのメモ")

うーん、ただ CentOS 7.2.1511 / kernel 3.10.0-327.el7.x86_64 で試している感じ `mount --make-private` しなくても大丈夫そうですけれども・・？

確かに `unshare -m` する前だとデフォで shared になっているんですが、`unshare -m` すると shared が落ちるようです。

```sh
cat /proc/$$/mountinfo | fgrep ' / / '
# 58 1 253:0 / / rw,relatime shared:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota

unshare -m /bin/bash

cat /proc/$$/mountinfo | fgrep ' / / '
# 82 81 253:0 / / rw,relatime - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
```

下記などを見た感じ、

- http://unix.stackexchange.com/questions/246312/why-is-my-bind-mount-visible-outside-its-mount-namespace
- https://bugzilla.redhat.com/show_bug.cgi?id=1209594
- https://rhn.redhat.com/errata/RHBA-2015-2093.html

これは、systemd でかつ `util-linux < 2.27` の場合の問題で、`util-linux >= 2.27` だと `unshare -m` で shared が伝播しないようになっており、RHEL/CentOS 7.2 にはそれがバックポートされているようです。

ので、RHEL/CentOS 7.2 なら `mount --make-private` は要らないっぽいです。