在多层(物理驱动器 -> md -> dm -> lvm)的情况下,调度程序、预读设置和其他磁盘设置如何交互?
假设您有多个磁盘 (/dev/sda - /dev/sdd),它们都是使用 mdadm 创建的软件 RAID 设备 (/dev/md0) 的一部分。每个设备(包括物理磁盘和 /dev/md0)都有自己的 IO 调度程序设置(像这样更改)和预读(使用 blockdev 更改)。当你加入 dm(加密)和 LVM 之类的东西时,你会添加更多具有自己设置的层。
例如,如果物理设备有 128 个数据块的预读,而 RAID 有 64 个数据块的预读,当我从 /dev/md0 读取时,这是正确的吗?md 驱动程序是否尝试读取 64 个块,然后物理设备驱动程序将其转换为 128 个块的读取?或者 RAID 预读是否“直通”到底层设备,导致读取 64 个块?
同样的问题也适用于调度程序?我是否必须担心多层 IO 调度程序以及它们如何交互,或者 /dev/md0 是否有效地覆盖了底层调度程序?
在我试图回答这个问题时,我挖掘了一些关于调度程序和工具的有趣数据,这些数据可能有助于解决这个问题:
如果您从 md0 读取,则使用 md0 的预读。如果您从作为 md0 组件的 sda 读取,那么它将使用 sda 设置。设备映射器只是将一个 I/O 拆分成多个读取和写入来执行 RAID,但这一切都在预读发生的块缓存层之下。存储堆栈如下所示:
文件系统 - 使用 O_DIRECT 打开时绕过缓存
块缓存 - 预读、写缓存、调度程序
设备映射器 - dm、lvm、软件 RAID、快照等。
sd - 磁盘驱动程序
SCSI - 错误处理、设备路由
硬件驱动程序 - scsi 卡、FC 卡、以太网
请注意,当您执行
dd if=/dev/sda of=foo
Run Code Online (Sandbox Code Playgroud)
您正在将 sda 作为文件读取,因此您正在通过块缓存。要直接转到磁盘,请执行
dd if=/dev/sda of=foo iflag=direct
Run Code Online (Sandbox Code Playgroud)
至于 I/O 电梯调度程序,它们只存在于磁盘驱动程序 (sd) 上。/sys/block/md 或 /sys/block/dm 下没有队列目录。您只需进行一次磁盘升降机排序。