背景
最近遇到了一个故障,在集群软件升级过程中,发现某一个磁盘分区变为只读,导致存储应用识别该磁盘不可用。调查发现集群升级过程中,会重新生成每个节点的 GRUB 配置文件,在执行 grub2-mkconfig
过程中导致的磁盘分区只读。记录下 grub2-mkconfig
命令执行到真正磁盘只读指令下发的流程。
调查
grub2-mkconfig
在执行 grub2-mkconfig
命令时,如果没有指定配置 GRUB_DISABLE_OS_PROBER=true
时,则 GRUB 会调用 os-prober (/etc/grub.d/30_os-prober)用于扫描其他操作系统进行后续配置。
os-prober
os-prober 是用来探测其他磁盘中存在操作系统的情况。通常由各个发行版本提供,源码地址:https://salsa.debian.org/installer-team/os-prober 。
CentOS 默认包含的 os-prober 与源码版本并不相同,包含了一些额外的配置,通过 RPM changelog 可以查看:
1 | Name : os-prober |
通过下载 os-prober 的 source RPM 可以查看具体改动内容,查看 os-prober.spec 文件,查看额外的 Patch 列表:
1 | Name: os-prober |
单独查看每一个 Patch 很麻烦,直接看操作系统上已经安装的 os-prober 相关文件:
1 | $rpm -ql os-prober |
grub2-mkconfig 调用 os-prober 流程
grub2-mkconfig
最终目的是生成 grub.cfg ,在执行过程中,会通过调用 /etc/grub.d/
路径下的配置脚本来依次执行,在 CentOS 存在 /etc/grub.d/30_os-prober
配置脚本。
执行 os-prober
的具体代码如下:1
2
3
4
5OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
if [ -z "${OSPROBED}" ] ; then
# empty os-prober output, nothing doing
exit 0
fi
CentOS os-prober 执行流程
- 创建新的 namespace,在调试 os-prober 过程中建议注释掉该行为
- 确保所有的文件系统类型是支持的,执行
/usr/libexec/os-prober/init/*
- 获取节点处于已挂载分区信息、swap 分区信息、RAID 设备分区信息
获取节点所有 partition 信息
- 如果 partition 已经存在于swap 分区信息或 RAID 设备分区信息中,则跳过
通过
blkid -o value -S type $path
获取文件系统信息作为 type,比如:
-1
2$blkid -o value -s TYPE /dev/vdb1
xfs_external_log- 如果 type == btrfs,则判断是否为 btrfs volume,如果是则过滤;如果不是,则使用
/usr/libexec/os-probes/50mounted-tests
针对该分区进行探测 - 如果分区不在已挂载分区信息中,则使用
/usr/libexec/os-probes/50mounted-tests
路径下的所有方式进行探测,遍历执行 - 如果分区处于已挂载分区信息中,则使用
/usr/libexec/os-probes/50mounted-tests
路径下的所有方式进行探测,遍历执行
- 如果 type == btrfs,则判断是否为 btrfs volume,如果是则过滤;如果不是,则使用
- 探测结束
CentOS /usr/libexec/os-probes/50mounted-tests
探测流程
- 参数校验,获取 partition 的 fs type 属性
- 如果 type 处于未探测、空、LVM、swap、ctypto、ntfs则直接退出
- 如果 type == btrfs ,则针对 subvolume 进行探测流程
- 如果节点存在 grub-mount ,存在 grub2-probe 则判断 partition 是否被GRUB 挂载
- 如果上述分支都没有进入,则将分区置为只读
- blockdev –setro $partition
- 并通过 trap 设置信号处理函数,当接收到 EXIT,HUP,INT,QUIT,TERM 信号时,则将partition 重新置为可读可写
- 将分区根据当前 type 类型挂载到临时挂载点下,试用
/usr/libexec/os-probes/mounted/
路径下的探测方式进行探测,遍历执行 - 探测结束
总结
如果你的节点上存在处于未被挂载,且文件系统类型不为空的情况,那么建议通过设置 GRUB 配置:GRUB_DISABLE_OS_PROBER=true
来禁用 os-prober 的执行,防止磁盘分区变为只读。