Arch Linuxシステム(Linuxカーネル3.14.2)で、バインドマウントが読み取り専用オプションを考慮しません
# mkdir test
# mount --bind -o ro test/ /mnt
# touch /mnt/foo
ファイル/mnt/foo
を作成します。 /proc/mounts
の関連エントリは
/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0
マウントオプションは、要求されたオプションとは一致しませんが、バインドマウントの読み取り/書き込み動作と、/dev/sda2
を最初にマウントするために使用されたオプションの両方に一致します/
/dev/sda2 / ext4 rw,noatime,data=ordered 0 0
ただし、マウントを再マウントすると、読み取り専用オプションが考慮されます
# mount --bind -o remount,ro test/ /mnt
# touch /mnt/bar
touch: cannot touch ‘/mnt/bar’: Read-only file system
および/proc/mounts/
の関連エントリ
/dev/sda2 /mnt ext4 ro,relatime,data=ordered 0 0
私が期待するように見えます(実際にはtest
ディレクトリの完全なパスが表示されることを期待しています)。 /proc/mounts/
上の/dev/sda2/
の元のマウントの/
のエントリも変更されず、読み取り/書き込みのままです
/dev/sda2 / ext4 rw,noatime,data=ordered 0 0
この動作と回避策は、少なくとも 2008 から既知であり、mount
のマニュアルページに記載されています。
ファイルシステムのマウントオプションは元のマウントポイントのオプションと同じままであり、-oオプションを--bind /-rbindと一緒に渡して変更することはできません。マウントオプションは、別のremountコマンドで変更できます。
すべてのディストリビューションが同じように動作するわけではありません。バインドマウントがマウントを読み取り専用にしない場合、Debianは警告を生成しますが、Archは暗黙のうちにオプションを尊重しません。
mount: warning: /mnt seems to be mounted read-write.
この動作はDebian Lenny and Squeeze で「修正」されたとの報告がありますが、 ユニバーサルフィックス ではないようであり、Debian Wheezyでも動作しません。バインドマウントで初期マウントの読み取り専用オプションを尊重することの難しさは何ですか?
バインドマウントは、まさに...バインドマウントです。つまり新しいマウントではありません。新しいマウントポイントとしてサブディレクトリを「リンク」/「公開」/「検討」するだけです。そのため、マウントパラメータを変更することはできません。それがあなたが不満を得ている理由です:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
しかし、あなたが言ったように、通常のバインドマウントは機能します:
# mount /mnt/1/lala /mnt/2 -o bind
そしてro remountも機能します:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
ただし、このバインドマウントだけでなく、マウント全体を変更することになります。/proc/mountsを見ると、バインドマウントと元のマウントの両方が読み取り専用に変更されていることがわかります。
/dev/loop0 /mnt/1 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0
/dev/loop0 /mnt/2 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0
つまり、あなたがしていることは、最初のマウントを読み取り専用マウントに変更し、その後バインドマウントを実行するようなもので、もちろん読み取り専用になります。
以下は、4.5カーネルには当てはまりますが、4.3カーネルには当てはまりません(これは誤りです。以下の更新#2を参照してください)。
カーネルには、読み取り専用を制御する2つのフラグがあります。
MS_READONLY
:マウントが読み取り専用かどうかを示しますMNT_READONLY
:「ユーザー」が読み取り専用かどうかを示します4.5カーネルでは、実際にmount -o bind,ro
を実行するとうまくいきます。たとえば、これ:
# mkdir /tmp/test
# mkdir /tmp/test/a /tmp/test/b
# mount -t tmpfs none /tmp/test/a
# mkdir /tmp/test/a/d
# mount -o bind,ro /tmp/test/a/d /tmp/test/b
/tmp/test/a/d
から/tmp/test/b
への読み取り専用バインドマウントが作成され、/proc/mounts
で次のように表示されます。
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
より詳細なビューは/proc/self/mountinfo
にあり、ユーザービュー(名前空間)を考慮しています。関連する行は次のとおりです。
363 74 0:49 / /tmp/test/a rw,relatime shared:273 - tmpfs none rw
368 74 0:49 /d /tmp/test/b ro,relatime shared:273 - tmpfs none rw
2行目には、ro
(MNT_READONLY
)とrw
(!MS_READONLY
)の両方が表示されていることがわかります。
最終結果はこれです:
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
これをもう少し掘り下げると、実際の動作はutil-linuxの一部であるlibmountのバージョンに依存することがわかります。これのサポートはthis commit で追加され、バージョン2.27でリリースされました。
commit 9ac77b8a78452eab0612523d27fee52159f5016a 作成者:Karel Zak 日付:月8月17日11:54:26 2015 +0200 libmount:「 bind、ro " これで、2つのmount(8)呼び出しを使用して、読み取り専用の マウントを作成する必要があります: mount/foo/bar -o bind mount/bar -o remount、ro、bind このパッチでは、「bind、ro」を指定して再マウントを行うことができます 追加のmount(2)syscallによってlibmountによって自動的に。もちろん、アトミックではありません。 アトミックではありません。
これも回避策を提供します。この動作は、古いマウントと新しいマウントでstraceを使用して確認できます。
古い:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
新着:
mount("/tmp/test/a/d", "/tmp/test/b", 0x1a8ee90, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.011492>
mount("none", "/tmp/test/b", NULL, MS_RDONLY|MS_REMOUNT|MS_BIND, NULL) = 0 <0.006281>
望ましい結果を得るには、2つのコマンドを実行する必要があります(@Thomasがすでに言ったように)。
mount SRC DST -o bind
mount DST -o remount,ro,bind
新しいバージョンのマウント(util-linux> = 2.27)を実行すると、これが自動的に行われます
mount SRC DST -o bind,ro
適切な解決策は、実際に2回マウントすることです。コマンドラインで:
mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir
/etc/fstab
:
/source/dir /destination/dir none bind 0 0
/source/dir /destination/dir none remount,bind,ro 0 0
マニュアル(man mount
)はそのように述べています:
The bind mounts. Since Linux 2.4.0 it is possible to remount part of the file hierarchy somewhere else. The call is mount --bind olddir newdir [...] Note that the filesystem mount options will remain the same as those on the original mount point, and cannot be changed by passing the -o option along with --bind/--rbind. The mount options can be changed by a separate remount command, for example: . mount --bind olddir newdir mount -o remount,ro newdir . Note that behavior of the remount operation depends on the /etc/mtab file. The first command stores the 'bind' flag to the /etc/mtab file and the second command reads the flag from the file. If you have a system without the /etc/mtab file or if you explicitly define source and target for the remount command (then mount(8) does not read /etc/mtab), then you have to use bind flag (or option) for the remount command too. For example: . mount --bind olddir newdir mount -o remount,ro,bind olddir newdir
mount(8)
コマンドライン(このサイトでは許容可能)の観点から質問しています。そのコマンドは他の回答で説明されており、場合によっては、必要な2番目のmount(2)
システムコールを抽象化しています。
しかし、なぜ2番目のシステムコールが必要なのでしょうか。単一のmount(2)
呼び出しで読み取り専用バインドマウントを作成できないのはなぜですか?
mount(2)
のマニュアルページ は、他の人が指摘したように、2つのセットのフラグがあることを説明しています設定中:
それは言う:
Linux 2.6.16以降、_
MS_RDONLY
_は、基になるファイルシステムだけでなく、マウントポイントごとに設定またはクリアできます。マウントされたファイルシステムは、ファイルシステムもマウントポイントも読み取り専用としてフラグが立てられていない場合にのみ書き込み可能になります。
そして_MS_REMOUNT
_に関して:
Linux 2.6.26以降、このフラグを_
MS_BIND
_とともに使用して、マウントポイントごとのフラグのみを変更できます。これは、基礎となるファイルシステムを変更せずにマウントポイントの「読み取り専用」フラグを設定またはクリアする場合に特に便利です。マウントフラグを次のように指定します。_MS_REMOUNT | MS_BIND | MS_RDONLY
_他のマウントポイントに影響を与えることなく、このマウントポイントを介して読み取り専用でアクセスします。
この問題は、バインドマウントが最初に導入されたときに発生したと思います。
Mountflagsに_
MS_BIND
_(Linux 2.4以降で使用可能)が含まれている場合は、バインドマウントを実行します。 ... _MS_REC
_を除いて、mountflags引数の残りのビットも無視されます。 (バインドマウントには、基礎となるマウントポイントと同じマウントオプションがあります。)
_MS_BIND | MS_REMOUNT
_をVFSフラグのみを設定する信号として使用する代わりに、_MS_RDONLY
_を最初の_MS_BIND
_とともに除外(および受け入れる)して、それを適用することを選択できたようですマウントポイントに。
したがって、mount(2)
システムコールのやや奇妙なセマンティクスのため、次のようになります。