A montagem de ligação é apenas ... bem ... uma montagem de ligação. Ou seja não é um novo monte. Apenas "links" / "expõe" / "considera" um subdiretório como um novo ponto de montagem. Como tal, não pode alterar os parâmetros de montagem. É por isso que você está recebendo reclamações:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
Mas, como você disse, uma montagem normal de bind funciona:
# mount /mnt/1/lala /mnt/2 -o bind
E então uma remontagem ro também funciona:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
No entanto, o que acontece é que você está mudando toda a montagem e não apenas essa montagem de ligação. Se você der uma olhada em / proc / mounts, verá que ambos bind mount e o mount original mudam para somente leitura:
/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
Então, o que você está fazendo é como mudar a montagem inicial para uma montagem somente leitura e então fazendo uma montagem de ligação que, naturalmente, será somente leitura.
ATUALIZAÇÃO 2016-07-20:
Os itens a seguir são verdadeiros para os kernels 4.5, mas não para os kernels 4.3 (Isso está errado. Veja a atualização 2 abaixo):
O kernel tem dois sinalizadores que controlam somente leitura:
- O
MS_READONLY
: indicando se a montagem é somente leitura - O
MNT_READONLY
: indicando se o "usuário" quer que ele seja somente leitura
Em um kernel 4.5, fazer um mount -o bind,ro
realmente fará o truque. Por exemplo, isso:
# 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
criará uma montagem de vinculação somente leitura de /tmp/test/a/d
a /tmp/test/b
, que será visível em /proc/mounts
como:
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
Uma visão mais detalhada é visível em /proc/self/mountinfo
, que leva em consideração a visão do usuário (namespace). As linhas relevantes serão estas:
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
Onde na segunda linha, você pode ver que ele diz tanto ro
( MNT_READONLY
) quanto rw
( !MS_READONLY
).
O resultado final é este:
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
ATUALIZAÇÃO 2016-07-20 # 2:
Um pouco mais sobre isso mostra que o comportamento de fato depende da versão do libmount que faz parte do util-linux. O suporte para isso foi adicionado com este commit e foi lançado com a versão 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
que também fornece a solução alternativa. O comportamento pode ser visto usando strace em uma montagem mais antiga e mais recente:
Antigo:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
Novo:
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>
Conclusão:
Para alcançar o resultado desejado, é necessário executar dois comandos (como @Thomas já disse):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Novas versões do mount (util-linux > = 2.27) fazem isso automaticamente quando se executa
mount SRC DST -o bind,ro