在工作中systemd-shutdown
,它用于mount()
将文件系统重新挂载为只读。
/* MS_REMOUNT requires that the data parameter
* should be the same from the original mount
* except for the desired changes. Since we want
* to remount read-only, we should filter out
* rw (and ro too, because it confuses the kernel) */
...filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
...mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options)...
但是当我查看时strace mount -oremount,rw /boot
,mount
系统调用传递了 NULL 作为其最后一个参数。这是否表明实际上没有必要复制和修改旧的选项字符串?
答案1
不。
如果您编辑/etc/fstab
并添加非通用选项foo
,/sbin/mount
则会将“foo”作为最后一个参数传递给mount()
。在您的示例中,它传递了 NULL,但我认为这意味着空 string ""
。想必它们具有相同的效果。
/sbin/mount
如果您同时传递路径和设备,显然行为会有所不同(!)。
重新挂载功能遵循 mount 命令与 fstab 中的选项配合使用的标准方式。这意味着仅当同时指定了 device 和 dir 时,mount 才不会读取 fstab(或 mtab)。
mount -o remount,rw /dev/foo /dir
在此调用之后,所有旧的挂载选项都将被替换,并且 fstab(或 mtab)中的任意内容都将被忽略,除了由 mount 命令内部生成和维护的 Loop= 选项。
mount -o remount,rw /dir
在此调用之后,mount 读取 fstab 并将这些选项与命令行 (-o) 中的选项合并。如果在 fstab 中找不到挂载点,则允许使用未指定的源重新挂载。
言外之意是,最后一种情况似乎也覆盖了挂载点的任何当前选项。
问题中引用的代码有些可疑。它似乎重置了安装标志。当前行为:
重新安装现有安装
... mountflags 和 data 参数应该与原始 mount() 调用中使用的值匹配,除了那些被故意更改的参数之外。
所以这可能就是评论的来源。
可以更改以下安装标志:MS_LAZYTIME、MS_MANDLOCK、MS_NOATIME、MS_NODEV、MS_NODIRATIME、MS_NOEXEC、MS_NOSUID、MS_RELATIME、MS_RDONLY 和 MS_SYNCHRONOUS。
我猜代码是现在工作正常。以只读方式重新挂载可以避免有关后续写入的问题,或者由于 blockdev 是只读而导致读写重新挂载被拒绝。systemd-shutdown
此时应该已将 SIGKILL 发送到有权访问文件系统的任何其他进程,因此我们可以忽略 NOEXEC 等安全选项。
在重新安装期间更改 MS_DIRSYNC 标志设置的尝试将被静默忽略。
尽管这意味着其他标志可能不会被默默地忽略,并且如果它们不匹配可能会导致调用失败,但我不认为核心内核代码会执行类似的操作。
从 Linux 3.17 开始,如果在 mountflags 中未指定 MS_NOATIME、MS_NODIRATIME、MS_RELATIME 或 MS_STRICTATIME 中的任何一个,则重新挂载操作将保留这些标志的现有值(而不是默认为 MS_RELATIME)。
从 Linux 2.6.26 开始,此标志还可以通过将 mountflags 指定为只读来使现有的绑定挂载变为只读:
MS_REMOUNT | MS_BIND | MS_RDONLY
我想 systemd-shutdown 没有以完全相同的方式处理 fstab 就好mount -oremount,ro /boot
了:)。 (旧的 sysvinit 脚本至少在 Debian 中没问题,因为除了根文件系统之外,它们不使用 remount RO)。