В моей системе Arch Linux (Linux Kernel 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/
on /
также не изменилась и остается доступной для чтения/записи
/dev/sda2 / ext4 rw,noatime,data=ordered 0 0
Такое поведение и способы его обхода известны по крайней мере с тех пор, как2008и задокументированы на странице руководстваmount
Обратите внимание, что параметры монтирования файловой системы останутся такими же, как и в исходной точке монтирования, и не могут быть изменены путем передачи параметра -o вместе с --bind/--rbind. Параметры монтирования можно изменить с помощью отдельной команды перемонтирования
Не все дистрибутивы ведут себя одинаково. Arch, похоже, молча не учитывает параметры, в то время как Debian выдает предупреждение, когда привязка монтирования не получает монтирование только для чтения
mount: warning: /mnt seems to be mounted read-write.
Есть сообщения, что это поведение было «исправлено» в Debian.Ленни и Сжимайхотя это, кажется, неуниверсальное решениеи это все еще не работает в Debian Wheezy. В чем сложность, связанная с тем, чтобы заставить bind mount уважать опцию только для чтения при первоначальном монтировании?
решение1
Bind mount — это просто... ну... bind mount. То есть это не новое монтирование. Оно просто "связывает"/"открывает"/"рассматривает" подкаталог как новую точку монтирования. Таким образом, оно не может изменить параметры монтирования. Вот почему вы получаете жалобы:
# 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 remount тоже работает:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
Однако происходит то, что вы меняете все монтирование, а не только это монтирование bind. Если вы посмотрите на /proc/mounts, вы увидите, что и монтирование bind, и исходное монтирование меняются на read-only:
/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 ниже):
Ядро имеет два флага, которые управляют режимом «только чтение»:
- : Указывает
MS_READONLY
, доступно ли монтирование только для чтения. - : Указывает
MNT_READONLY
, хочет ли «пользователь» иметь доступ только для чтения.
На ядре 4.5 выполнение a 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
( 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:
Немного покопавшись в этом, мы видим, что поведение на самом деле зависит от версии libmount, которая является частью util-linux. Поддержка этого была добавлена с помощью этогосовершитьи был выпущен с версией 2.27:
совершить 9ac77b8a78452eab0612523d27fee52159f5016a Автор: Карел Зак Дата: Пн 17 авг 11:54:26 2015 +0200 libmount: добавлена поддержка "bind,ro" Теперь необходимо использовать два вызова mount(8) для создания файла, доступного только для чтения. устанавливать: монтировать /foo /bar -o привязать mount /bar -o перемонтировать,ro,bind Этот патч позволяет указать «bind,ro» и перемонтирование будет выполнено. автоматически с помощью libmount с помощью дополнительного системного вызова mount(2). Это не атомный конечно. Подписано: Карел Зак
что также обеспечивает обходной путь. Поведение можно увидеть, используя 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>
Заключение:
Для достижения желаемого результата необходимо выполнить две команды (как уже сказал @Thomas):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Более новые версии mount (util-linux >=2.27) делают это автоматически при запуске
mount SRC DST -o bind,ro
решение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)
командной строки (что приемлемо на этом сайте). Эта команда обсуждалась в других ответах и в некоторых случаях абстрагируется от необходимого второго mount(2)
системного вызова.
Но зачем нужен второй системный вызов? Почему один mount(2)
вызов не может создать read-only bind mount?
Themount(2)
страница руководстваобъясняет, что, как уже отмечали другие, существуютдва набораиз устанавливаемых флагов:
- Базовые флаги файловой системы
- Флаги точки монтирования VFS
Там говорится:
Начиная с Linux 2.6.16,
MS_RDONLY
может быть установлен или очищен на основе точки монтирования, а также на основе базовой файловой системы. Смонтированная файловая система будет доступна для записи только в том случае, если ни файловая система, ни точка монтирования не помечены как доступные только для чтения.
И относительно MS_REMOUNT
:
Начиная с Linux 2.6.26, этот флаг можно использовать
MS_BIND
для изменения только флагов per-mount-point. Это особенно полезно для установки или снятия флага "только для чтения" на точке монтирования без изменения базовой файловой системы. Указание mountflags как:MS_REMOUNT | MS_BIND | MS_RDONLY
сделает доступ через эту точку монтирования только для чтения, не затрагивая другие точки монтирования.
Я думаю, что проблема возникла, когда впервые были введены привязные крепления:
Если mountflags включает
MS_BIND
(доступно с Linux 2.4), то выполнить монтирование привязки. ... Остальные биты в аргументе mountflags также игнорируются, за исключениемMS_REC
. (Монтирование привязки имеет те же параметры монтирования, что и базовая точка монтирования.)
Похоже, что вместо использования MS_BIND | MS_REMOUNT
в качестве сигнала для установки только флагов VFS, они могли бы выбрать исключение (и принятие) MS_RDONLY
вместе с начальным MS_BIND
и применить его к точке монтирования.
Итак, из-за несколько странной семантики системного mount(2)
вызова:
- Первый вызов создает привязку монтирования, а все остальные флаги игнорируются.
- Второй вызов (с повторным монтированием) устанавливаетТочка монтированияфлаги только для чтения