私の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これらは、manページに記載されています。mount
ファイルシステムのマウントオプションは元のマウントポイントと同じままであり、--bind/--rbindとともに-oオプションを渡しても変更できないことに注意してください。マウントオプションは別の再マウントコマンドで変更できます。
すべてのディストリビューションが同じ動作をするわけではありません。Arch はオプションを黙って尊重しないようですが、Debian はバインドマウントが読み取り専用でマウントされない場合に警告を発します。
mount: warning: /mnt seems to be mounted read-write.
この動作はDebianで「修正」されたという報告があるレニーとスクイーズそれはそうではないようですがユニバーサルフィックスまた、Debian Wheezy でもまだ動作しません。バインド マウントが初期マウントの読み取り専用オプションを尊重するようにすることの難しさは何ですか?
答え1
バインド マウントは、まさに... バインド マウントです。つまり、新しいマウントではありません。サブディレクトリを新しいマウント ポイントとして「リンク」/「公開」/「考慮」するだけです。そのため、マウント パラメータを変更することはできません。これが、次のような苦情が寄せられる理由です。
# 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 の再マウントも機能します:
# 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
つまり、最初のマウントを読み取り専用マウントに変更し、それから当然ながら読み取り専用となるバインドマウントを実行します。
2016-07-20更新:
以下は 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
ro
2行目には、 ( 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
2016-07-20 更新 #2:
もう少し調べてみると、この動作は実際にはutil-linuxの一部であるlibmountのバージョンに依存していることがわかります。これに対するサポートはこれで追加されました。専念バージョン 2.27 でリリースされました:
コミット 9ac77b8a78452eab0612523d27fee52159f5016a 著者: カレル・ザック 日付: 2015 年 8 月 17 日月曜日 11:54:26 +0200 libmount: 「bind,ro」のサポートを追加 読み取り専用を作成するには、2つのmount(8)呼び出しを使用する必要があります。 マウント: /foo /bar をマウント -o バインド マウント /bar -o 再マウント、ro、バインド このパッチにより、「bind,ro」を指定でき、再マウントが実行されます。 libmountによって自動的にマウントされます。これは もちろん原子です。 署名者: Karel Zak
回避策も提供されています。動作は、古いマウントと新しいマウントで 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
新しいバージョンのmount(util-linux >=2.27)では、実行時にこれを自動的に実行します。
mount SRC DST -o bind,ro
答え2
適切な解決策は、実際に 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
答え3
あなたはコマンドラインの観点から質問していますmount(8)
(このサイトではそれが許容されます)。そのコマンドは他の回答で説明されており、場合によっては必要な 2 番目のシステム コールを抽象化しますmount(2)
。
しかし、なぜ 2 番目のシステム コールが必要なのでしょうか? 1 回のmount(2)
呼び出しで読み取り専用のバインド マウントを作成できないのはなぜでしょうか?
のmount(2)
マニュアルページ他の人が指摘したように、2セット設定されているフラグ:
- 基礎となるファイルシステムフラグ
- VFSマウントポイントフラグ
それはこう言います:
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 以降で使用可能)、バインド マウントを実行します。... mountflags 引数の残りのビットも、 を除いて無視されますMS_REC
。(バインド マウントには、基礎となるマウント ポイントと同じマウント オプションがあります。)
をシグナルとして使用して VFS フラグのみを設定する代わりに、最初の とともにを除いて (受け入れて) 、マウント ポイントに適用することMS_BIND | MS_REMOUNT
もできたようです。MS_RDONLY
MS_BIND
mount(2)
システム コールのセマンティクスがやや奇妙なため、次のようになります。
- 最初の呼び出しはバインドマウントを作成し、他のすべてのフラグは無視されます
- 2回目の呼び出し(再マウントあり)では、マウントポイント読み取り専用フラグ