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

More than 3 years have passed since last update.

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

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

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


  • 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 でも見えるようになります。

mount --bind /usr /mnt

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

ls /usr/bin

ls /mnt/bin

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

mount --bind /proc/$$ /mnt

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


mount --rbind

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

mount --bind / /mnt

ll /mnt/proc/
# total 0

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

mount --rbind / /mnt

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

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

umount -R /mnt


mount --make-shared

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

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

mount --bind /media /mnt

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

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 を共有マウントポイントにして、

mount --bind /media /media

mount --make-shared /media

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

mount --bind /media /mnt

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

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 から見ることができます。

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 を共有マウントポイントにします。

mount --bind /media /media

mount --make-shared /media

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

mount --bind /media /mnt

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

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

mount --make-slave /mnt

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

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 にマウントして、

mount --bind /media /media

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

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

mount --make-private /mnt

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

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 できなくなります。

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 はいずれも再帰的な効果はないため、例えば次のように / をバインド不可にしても、

mount --make-unbindable /

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

mount --bind /proc /mnt

ll /proc
# total 0
# dr-xr-xr-x. 9 root root 0 May 7 02:33 1
:

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

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 も再帰的に適用することができます。

mount --make-rshared /mnt

mount --make-rslave /mnt
mount --make-rprivate /mnt


unshare -m と mount --make-private

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

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

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

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

下記などを見た感じ、

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

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