Str*_*Bad 38 linux mount readonly bind-mount
在我的 Arch Linux 系统(Linux Kernel 3.14.2)上,绑定挂载不遵守只读选项
# mkdir test
# mount --bind -o ro test/ /mnt
# touch /mnt/foo
Run Code Online (Sandbox Code Playgroud)
创建文件/mnt/foo
。相关条目/proc/mounts
是
/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0
Run Code Online (Sandbox Code Playgroud)
安装选项不符合我要求的选择,但这样做同时匹配绑定的读/写性能和安装使用的选项最初安装/dev/sda2
上/
/dev/sda2 / ext4 rw,noatime,data=ordered 0 0
Run Code Online (Sandbox Code Playgroud)
但是,如果我重新安装挂载,则它尊重只读选项
# mount --bind -o remount,ro test/ /mnt
# touch /mnt/bar
touch: cannot touch ‘/mnt/bar’: Read-only file system
Run Code Online (Sandbox Code Playgroud)
和相关条目 /proc/mounts/
/dev/sda2 /mnt ext4 ro,relatime,data=ordered 0 0
Run Code Online (Sandbox Code Playgroud)
看起来像我所期望的(尽管实际上我希望看到test
目录的完整路径)。on/proc/mounts/
的原始挂载入口也没有变化,保持读/写/dev/sda2/
/
/dev/sda2 / ext4 rw,noatime,data=ordered 0 0
Run Code Online (Sandbox Code Playgroud)
这种行为和解决方法至少从2008 年就已为人所知,并记录在mount
请注意,文件系统挂载选项将与原始挂载点上的相同,并且无法通过将 -o 选项与 --bind/--rbind 一起传递来更改。可以通过单独的重新安装命令更改安装选项
并非所有发行版的行为都相同。Arch 似乎默默地不尊重这些选项,而当绑定挂载未以只读方式挂载时,Debian 会生成警告
mount: warning: /mnt seems to be mounted read-write.
Run Code Online (Sandbox Code Playgroud)
有报道称这种行为在 Debian Lenny 和 Squeeze 中被“修复”,尽管它似乎不是一个通用的修复,也不能在 Debian Wheezy 中工作。使绑定安装尊重初始安装上的只读选项有什么困难?
V13*_*V13 25
绑定坐骑只是……嗯……绑定坐骑。即它不是一个新的坐骑。它只是“链接”/“公开”/“考虑”一个子目录作为新的挂载点。因此它不能改变挂载参数。这就是您收到投诉的原因:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
Run Code Online (Sandbox Code Playgroud)
但是正如您所说,正常的绑定安装有效:
# mount /mnt/1/lala /mnt/2 -o bind
Run Code Online (Sandbox Code Playgroud)
然后 ro 重新安装也有效:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
Run Code Online (Sandbox Code Playgroud)
但是,发生的情况是您正在更改整个安装,而不仅仅是这个绑定安装。如果您查看 /proc/mounts,您会看到绑定安装和原始安装都更改为只读:
/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
Run Code Online (Sandbox Code Playgroud)
因此,您所做的就像将初始挂载更改为只读挂载,然后进行绑定挂载,这当然是只读的。
以下内容适用于 4.5 内核,但不适用于 4.3 内核(这是错误的。请参阅下面的更新 #2):
内核有两个控制只读的标志:
MS_READONLY
:指示是否安装为只读MNT_READONLY
:表示“用户”是否需要它只读在 4.5 内核上,执行 amount -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
Run Code Online (Sandbox Code Playgroud)
将创建一个只读绑定安装/tmp/test/a/d
to /tmp/test/b
,它将在以下位置可见/proc/mounts
:
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
Run Code Online (Sandbox Code Playgroud)
在 中可以看到更详细的视图/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
Run Code Online (Sandbox Code Playgroud)
在第二行的位置,您可以看到它同时表示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
Run Code Online (Sandbox Code Playgroud)
进一步深入研究表明,行为实际上取决于 libmount 的版本,它是 util-linux 的一部分。此提交添加了对此的支持,并随 2.27 版一起发布:
提交 9ac77b8a78452eab0612523d27fee52159f5016a 添加一名作者 日期:2015 年 8 月 17 日星期一 11:54:26 +0200 libmount:添加对“bind,ro”的支持 现在没有必要使用两个 mount(8) 调用来创建一个只读的 山: 挂载 /foo /bar -o 绑定 挂载 /bar -o 重新挂载,ro,bind 此补丁允许指定“bind,ro”并完成重新安装 通过额外的 mount(2) 系统调用由 libmount 自动执行。它不是 当然是原子的。 签字人:Karel Zak
这也提供了解决方法。在较旧和较新的安装上使用 strace 可以看到该行为:
老的:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
Run Code Online (Sandbox Code Playgroud)
新的:
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>
Run Code Online (Sandbox Code Playgroud)
为了达到预期的结果,需要运行两个命令(正如@Thomas 已经说过的):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Run Code Online (Sandbox Code Playgroud)
较新版本的 mount (util-linux >=2.27) 在运行时会自动执行此操作
mount SRC DST -o bind,ro
Run Code Online (Sandbox Code Playgroud)
正确的解决方案实际上是将其安装两次。在命令行上:
mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir
Run Code Online (Sandbox Code Playgroud)
在/etc/fstab
:
/source/dir /destination/dir none bind 0 0
/source/dir /destination/dir none remount,bind,ro 0 0
Run Code Online (Sandbox Code Playgroud)
手册 ( man mount
) 是这样说的:
Run Code Online (Sandbox Code Playgroud)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
归档时间: |
|
查看次数: |
24254 次 |
最近记录: |