Le montage lié est juste... eh bien... un montage lié. C'est à dire. ce n'est pas une nouvelle monture. Il se contente de "lier"/"exposer"/"considérer" un sous-répertoire comme un nouveau point de montage. En tant que tel, il ne peut pas modifier les paramètres de montage. C'est pourquoi vous recevez des plaintes :
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
Mais comme vous l'avez dit, un montage de liaison normal fonctionne :
# mount /mnt/1/lala /mnt/2 -o bind
Et puis un remontage ro fonctionne aussi :
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
Cependant, ce qui se passe, c'est que vous modifiez l'ensemble de la monture et pas seulement cette monture de liaison. Si vous jetez un œil à /proc/mounts, vous verrez que le montage lié et le montage d'origine passent en lecture seule :
/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
Donc, ce que vous faites, c'est comme changer le montage initial en un montage en lecture seule et puis faire un montage lié qui sera bien sûr en lecture seule.
MISE À JOUR 2016-07-20 :
Ce qui suit est vrai pour les noyaux 4.5, mais pas vrai pour les noyaux 4.3 (c'est faux. Voir la mise à jour #2 ci-dessous) :
Le noyau a deux drapeaux qui contrôlent la lecture seule :
- Le
MS_READONLY
:Indique si le montage est en lecture seule - Le
MNT_READONLY
:Indique si "l'utilisateur" le souhaite en lecture seule
Sur un noyau 4.5, faire un mount -o bind,ro
fera effectivement l'affaire. Par exemple, ceci :
# 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
créera un montage lié en lecture seule de /tmp/test/a/d
à /tmp/test/b
, qui sera visible en /proc/mounts
comme :
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
Une vue plus détaillée est visible en /proc/self/mountinfo
, qui tient compte de la vue utilisateur (espace de noms). Les lignes pertinentes seront celles-ci :
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
Où sur la deuxième ligne, vous pouvez voir qu'il est écrit à la fois ro
(MNT_READONLY
) et rw
(!MS_READONLY
).
Le résultat final est le suivant :
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
MISE À JOUR 2016-07-20 #2 :
Un peu plus en approfondissant cela montre que le comportement dépend en fait de la version de libmount qui fait partie de util-linux. La prise en charge de cela a été ajoutée avec ce commit et a été publiée avec la version 2.27 :
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
qui fournit également la solution de contournement. Le comportement peut être vu en utilisant strace sur un montage plus ancien et plus récent :
Ancien :
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
Nouveau :
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>
Conclusion :
Pour obtenir le résultat souhaité, il faut exécuter deux commandes (comme @Thomas l'a déjà dit) :
mount SRC DST -o bind
mount DST -o remount,ro,bind
Les nouvelles versions de mount (util-linux>=2.27) le font automatiquement quand on s'exécute
mount SRC DST -o bind,ro
La bonne solution est vraiment de le monter deux fois.Sur la ligne de commande :
mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir
En /etc/fstab
:
/source/dir /destination/dir none bind 0 0
/source/dir /destination/dir none remount,bind,ro 0 0
Le manuel (man mount
) le dit ainsi :
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