重新挂载只读而不更改其他选项

sou*_*edi 5 linux system-calls mount

在 上工作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)...
Run Code Online (Sandbox Code Playgroud)

但是当我查看时strace mount -oremount,rw /bootmount系统调用被传递为 NULL 作为它的最后一个参数。这是否表明实际上没有必要复制和破坏旧的选项字符串?

sou*_*edi 5

不。

如果您编辑/etc/fstab并添加一个非通用选项foo/sbin/mount则将“foo”作为最后一个参数传递给mount(). 在您的示例中,它传递了 NULL,但我认为这意味着空字符串""。据推测,它们具有相同的效果。


/sbin/mount如果您同时传递路径和设备 (!),则行为显然会有所不同。

重新挂载功能遵循挂载命令与 fstab 中的选项一起工作的标准方式。这意味着仅当同时指定了 device 和 dir 时,mount 才不会读取 fstab(或 mtab)。

 mount -o remount,rw /dev/foo /dir
Run Code Online (Sandbox Code Playgroud)

在此调用之后,所有旧的挂载选项都将被替换,fstab(或 mtab)中的任意内容将被忽略,除了由 mount 命令内部生成和维护的 loop= 选项。

 mount -o remount,rw  /dir
Run Code Online (Sandbox Code Playgroud)

在此调用之后,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
Run Code Online (Sandbox Code Playgroud)

我想这也是 systemd-shutdown 没有以完全相同的方式处理 fstab 的方式mount -oremount,ro /boot:)。(旧的 sysvinit 脚本至少在 Debian 中是可以的,因为除了根文件系统之外,它们不使用重新挂载 RO)。