Bindungshalterung ist nur ... naja ... eine Bindungshalterung. Dh es ist kein neues Reittier. Es "verlinkt"/"zeigt"/"erkennt" nur ein Unterverzeichnis als neuen Einhängepunkt. Als solches kann es die Mount-Parameter nicht ändern. Aus diesem Grund erhalten Sie Beschwerden:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
Aber wie Sie sagten, funktioniert ein normales Bind-Mount:
# mount /mnt/1/lala /mnt/2 -o bind
Und dann funktioniert auch ein ro remount:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
Was jedoch passiert, ist, dass Sie die gesamte Halterung ändern und nicht nur diese Bindungshalterung. Wenn Sie einen Blick auf /proc/mounts werfen, werden Sie feststellen, dass sowohl das Bind-Mount als auch das Original-Mount schreibgeschützt sind:
/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
Was Sie also tun, ist wie das Ändern des anfänglichen Mounts in ein schreibgeschütztes Mount und dann einen Bind-Mount durchführen, der natürlich schreibgeschützt sein wird.
AKTUALISIERUNG 2016-07-20:
Folgendes gilt für 4.5-Kernel, aber nicht für 4.3-Kernel (Das ist falsch. Siehe Update Nr. 2 unten):
Der Kernel hat zwei Flags, die den Nur-Lesen-Zustand steuern:
- Der
MS_READONLY
:Gibt an, ob das Mount schreibgeschützt ist - Die
MNT_READONLY
:Gibt an, ob der "Benutzer" es nur lesen möchte
Führen Sie auf einem 4.5-Kernel einen mount -o bind,ro
aus wird tatsächlich den Trick tun. Zum Beispiel dies:
# 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
erstellt einen schreibgeschützten Bind-Mount von /tmp/test/a/d
bis /tmp/test/b
, die in /proc/mounts
sichtbar sein wird als:
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
Eine detailliertere Ansicht ist in /proc/self/mountinfo
sichtbar , die die Benutzersicht (Namensraum) berücksichtigt. Die relevanten Zeilen lauten wie folgt:
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
Wo in der zweiten Zeile können Sie sehen, dass sowohl ro
steht (MNT_READONLY
) und rw
(!MS_READONLY
).
Das Endergebnis ist dieses:
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
UPDATE 2016-07-20 Nr. 2:
Ein bisschen mehr Nachforschungen zeigen, dass das Verhalten tatsächlich von der Version von libmount abhängt, die Teil von util-linux ist. Die Unterstützung dafür wurde mit diesem Commit hinzugefügt und mit Version 2.27 veröffentlicht:
commit 9ac77b8a78452eab0612523d27fee52159f5016a Author: Karel Zak Date: Mon Aug 17 11:54:26 2015 +0200 libmount: add support for "bind,ro" Now it's necessary t use two mount(8) calls to create a read-only mount: mount /foo /bar -o bind mount /bar -o remount,ro,bind This patch allows to specify "bind,ro" and the remount is done automatically by libmount by additional mount(2) syscall. It's not atomic of course. Signed-off-by: Karel Zak
die auch die Problemumgehung bietet. Das Verhalten kann mit strace auf einem älteren und einem neueren Mount gesehen werden:
Alt:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
Neu:
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>
Schlussfolgerung:
Um das gewünschte Ergebnis zu erzielen, müssen zwei Befehle ausgeführt werden (wie @Thomas bereits sagte):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Neuere Versionen von mount (util-linux>=2.27) tun dies automatisch, wenn eines ausgeführt wird
mount SRC DST -o bind,ro
Die richtige Lösung ist wirklich, es zweimal zu mounten. Auf der Kommandozeile:
mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir
Unter /etc/fstab
:
/source/dir /destination/dir none bind 0 0
/source/dir /destination/dir none remount,bind,ro 0 0
Das Handbuch (man mount
) gibt es so aus:
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