Bind mount è solo... beh... un bind mount. Cioè. non è una nuova montatura. Semplicemente "collega"/"espone"/"considera" una sottodirectory come un nuovo punto di montaggio. Come tale non può alterare i parametri di montaggio. Ecco perché ricevi reclami:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
Ma come hai detto, un normale bind mount funziona:
# mount /mnt/1/lala /mnt/2 -o bind
E poi funziona anche un ro remount:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
Tuttavia, ciò che accade è che stai cambiando l'intero supporto e non solo questo supporto di collegamento. Se dai un'occhiata a /proc/mounts vedrai che sia il bind mount che il mount originale cambiano in sola lettura:
/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
Quindi quello che stai facendo è come cambiare il montaggio iniziale in un montaggio di sola lettura e quindi eseguendo un bind mount che ovviamente sarà di sola lettura.
AGGIORNAMENTO 20-07-2016:
Quanto segue è vero per i kernel 4.5, ma non vero per i kernel 4.3 (questo è sbagliato. Vedi l'aggiornamento n. 2 di seguito):
Il kernel ha due flag che controllano la sola lettura:
- Il
MS_READONLY
:indica se il montaggio è di sola lettura - Il
MNT_READONLY
:Indica se l'"utente" lo desidera in sola lettura
Su un kernel 4.5, eseguendo un mount -o bind,ro
farà davvero il trucco. Ad esempio, questo:
# 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
creerà un mount bind di sola lettura di /tmp/test/a/d
a /tmp/test/b
, che sarà visibile in /proc/mounts
come:
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
Una vista più dettagliata è visibile in /proc/self/mountinfo
, che prende in considerazione la visualizzazione dell'utente (spazio dei nomi). Le righe pertinenti saranno queste:
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
Dove sulla seconda riga, puoi vedere che dice sia ro
(MNT_READONLY
) e rw
(!MS_READONLY
).
Il risultato finale è questo:
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
AGGIORNAMENTO 20-07-2016 n. 2:
Un po' più in profondità mostra che il comportamento in effetti dipende dalla versione di libmount che fa parte di util-linux. Il supporto per questo è stato aggiunto con questo commit ed è stato rilasciato con la versione 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
che fornisce anche la soluzione alternativa. Il comportamento può essere visto usando strace su una montatura più vecchia e una più recente:
Vecchio:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
Novità:
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>
Conclusione:
Per ottenere il risultato desiderato è necessario eseguire due comandi (come già detto da @Thomas):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Le versioni più recenti di mount (util-linux>=2.27) lo fanno automaticamente quando ne viene eseguito uno
mount SRC DST -o bind,ro
La soluzione corretta è in realtà montarlo due volte. Sulla riga di comando:
mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir
In /etc/fstab
:
/source/dir /destination/dir none bind 0 0
/source/dir /destination/dir none remount,bind,ro 0 0
Il manuale (man mount
) lo afferma in questo modo:
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