RAID 阵列¶
引导时组装 RAID 阵列¶
- 管理 md 设备的工具可以在此处找到:
您可以使用以下内核命令行引导您的 md 设备
适用于不带持久超级块的旧式 raid 阵列
md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
适用于带有持久超级块的 raid 阵列
md=<md device no.>,dev0,dev1,...,devn
或者,组装一个可分区的阵列
md=d<md device no.>,dev0,dev1,...,devn
md device no.¶
md 设备的编号
|
device |
|---|---|
0 |
md0 |
1 |
md1 |
2 |
md2 |
3 |
md3 |
4 |
md4 |
raid level¶
RAID 阵列的级别
|
level |
|---|---|
-1 |
线性模式 (linear) |
0 |
带区模式 (striped) |
其他模式仅支持持久超级块
chunk size factor¶
(仅适用于 raid-0 和 raid-1)
设置块大小(chunk size)为 4k << n。
fault level¶
完全忽略
dev0 到 devn¶
例如 /dev/hda1, /dev/hdc1, /dev/sda1, /dev/sdb1
一个可能的 loadlin 命令行(Harald Hoyer <HarryH@Royal.Net>)如下所示
e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
引导时 RAID 阵列的自动检测¶
当 md 被编译进内核(而非作为模块)时,类型为 0xfd 的分区将被扫描并自动组装成 RAID 阵列。可以使用内核参数 raid=noautodetect 禁用此自动检测。从内核 2.6.9 开始,只有带有 0 型超级块的驱动器可以在引导时自动检测并运行。
内核参数 raid=partitionable (或 raid=part) 意味着所有自动检测到的阵列都作为可分区阵列组装。
引导时组装降级/脏阵列¶
如果 raid5 或 raid6 阵列既是脏的(dirty)又是降级的(degraded),它可能会发生无法检测到的数据损坏。这是因为 脏 意味着校验数据不可信,而 降级 意味着某些数据块丢失且无法可靠重建(由于没有校验数据)。
由于这个原因,md 通常会拒绝启动此类阵列。这需要系统管理员采取行动,在存在损坏可能的情况下显式启动阵列。通常通过以下方式完成
mdadm --assemble --force ....
如果阵列包含根文件系统,此选项实际上不可用。为了支持从这种阵列引导,md 支持一个模块参数 start_dirty_degraded,当设置为 1 时,它将绕过检查并允许启动脏降级阵列。
因此,要使用脏降级 raid 5 或 6 的根文件系统进行引导,请使用
md-mod.start_dirty_degraded=1
超级块格式¶
md 驱动程序支持多种不同的超级块格式。目前支持超级块格式 0.90.0 以及在 2.5 开发系列中引入的 md-1 格式。
内核会自动检测正在使用的超级块格式。
由于历史原因,超级块格式 0 的处理方式与其他格式不同——它是最初的超级块格式。
通用规则 - 适用于所有超级块格式¶
通过向所有设备写入相应的超级块来 创建 阵列。
通过将这些设备中的每一个与特定的 md 虚拟设备关联来 组装 阵列。一旦完全组装,即可对其进行访问。
阵列应由用户空间工具创建。这将向所有设备写入超级块。它通常会将阵列标记为 不洁(unclean),或者某些设备缺失,以便内核 md 驱动程序可以创建适当的冗余(在 raid 1 中复制,在 raid 4/5 中进行校验计算)。
组装阵列时,首先使用 SET_ARRAY_INFO ioctl 进行初始化。这主要包含主版本号和次版本号。主版本号选择要使用的超级块格式。次版本号可能用于微调格式的处理,例如建议在每个设备的哪个位置寻找超级块。
然后使用 ADD_NEW_DISK ioctl 添加每个设备。这主要提供识别要添加设备的主设备号和次设备号。
使用 RUN_ARRAY ioctl 启动阵列。
启动后,可以添加新设备。应在其中写入适当的超级块,然后通过 ADD_NEW_DISK 传入。
故障或尚未激活的设备可以使用 HOT_REMOVE_DISK 从阵列中卸载。
适用于 0 格式超级块阵列以及无超级块阵列(非持久)的特定规则¶
可以通过在 SET_ARRAY_INFO ioctl 中描述阵列(级别、块大小等)来 创建 阵列。这必须满足 major_version==0 且 raid_disks != 0。
然后可以使用 ADD_NEW_DISK 添加未初始化的设备。传递给 ADD_NEW_DISK 的结构体必须指定设备的状态及其在阵列中的角色。
一旦使用 RUN_ARRAY 启动,就可以使用 HOT_ADD_DISK 添加未初始化的备用盘。
sysfs 中的 md 设备¶
md 设备在 sysfs (/sys) 中显示为常规块设备,例如:
/sys/block/md0
每个 md 设备都包含一个名为 md 的子目录,其中包含有关该设备的进一步 md 特定信息。
所有 md 设备都包含:
- level
一个指示
raid level(RAID 级别)的文本文件。例如 raid0, raid1, raid5, linear, multipath, faulty。如果尚未设置 raid 级别(阵列仍在组装中),该值将反映已写入其中的内容,可能是一个类似上述的名称,也可能是一个数字,如0,5等。- raid_disks
一个包含简单数字的文本文件,指示功能完备的阵列中的设备数量。如果尚不清楚,该文件将为空。如果阵列正在调整大小,这将包含新的设备数量。某些 raid 级别允许在阵列处于活动状态时设置此值,这将会重新配置阵列。否则,只能在组装阵列时设置。如果更改此属性会减小阵列大小,则不允许更改。要减少例如 raid5 中的驱动器数量,必须首先通过设置
array_size属性来减小阵列大小。- chunk_size
这是块(chunk)的大小(以字节为单位),仅与涉及带区化的 raid 级别(0,4,5,6,10)相关。阵列的地址空间在概念上被划分为块,连续的块被条带化到相邻的设备上。大小应至少为 PAGE_SIZE (4k) 且应为 2 的幂。这只能在组装阵列时设置。
- layout
阵列针对特定级别的
布局。这仅仅是一个数字,由不同的级别进行不同的解释。它可以在组装阵列时写入。- array_size
这可用于人为地将阵列中的可用空间限制为小于组合设备上实际可用的空间。写入一个小于可用大小的数字(以 KB 为单位)将设置该大小。阵列的任何重新配置(例如添加设备)都不会导致大小改变。写入单词
default将使阵列的有效大小恢复为基于level、chunk_size和component_size实际可用的任何大小。这可用于在减少 raid4/5/6 中的设备数量之前减小阵列大小,或用于支持强制执行此类裁剪的外部元数据格式。
- logical_block_size
配置阵列的逻辑块大小(以字节为单位)。此属性仅支持 1.x 元数据。在启动阵列之前写入该值。最终阵列的 LBS 使用此配置与所有组合设备的 LBS 之间的最大值。请注意,在 RAID 支持 folio 之前,LBS 不能超过 PAGE_SIZE。警告:在新内核上创建的阵列由于填充检查而无法在旧内核上组装,将模块参数 ‘check_new_feature’ 设置为 false 可以绕过,但可能会发生数据丢失。
- reshape_position
这可以是
none或阵列设备内的扇区号,指示重塑(reshape)的进度。如果设置了此项,则上述三个属性(raid_disks, chunk_size, layout)可能有 2 个值:旧值和新值。如果这些值不同,读取该属性会返回:new (old)并且写入将影响
新值,保持旧值不变。- component_size
对于具有数据冗余的阵列(即非 raid0、linear、faulty、multipath),所有组件必须具有相同的大小——或者至少必须有一个它们都能提供空间的大小。这是阵列几何结构的关键部分。它以扇区为单位,并可从此处读取。如果 personality 支持(raid1, raid5, raid6)且组件驱动器足够大,写入此值可能会调整阵列的大小。
- metadata_version
这指示用于记录阵列元数据的格式。它可以是 0.90(传统格式)、1.0、1.1、1.2(位置不同的较新格式)或
none,表示内核根本不管理元数据。或者它可以是external:后跟一个由用户空间设置的字符串。这表示元数据由用户空间程序管理。任何需要元数据更新的设备故障或其他事件都将导致阵列活动挂起,直到事件得到确认。- resync_start
应开始重新同步的点。如果不需要重新同步,这将是一个非常大的数字(或自 2.6.30-rc1 以来为
none)。在创建阵列时,它默认为 0,但将阵列作为clean(干净)启动会将其设置得大得多。- new_dev
此文件可写但不可读。写入的值应为 major:minor 格式的块设备号,例如 8:0。如果该设备可用,这将导致该设备附加到阵列。然后它将出现在 md/dev-XXX(取决于设备名称),并可以进行进一步配置。
- safe_mode_delay
当 md 阵列在一定时间内没有收到写请求时,它将被标记为
干净(clean)。当另一个写请求到达时,在写入开始之前阵列被标记为脏(dirty)。这被称为安全模式。一定时间由该文件控制,该文件以秒数存储该时间段。默认值为 200 毫秒 (0.200)。写入 0 将禁用安全模式。- array_state
此文件包含一个描述阵列当前状态的单词。在许多情况下,可以通过写入所需状态的单词来设置状态,但某些状态无法显式设置,且某些状态转换是不允许的。
Select/poll 适用于此文件。除 Active_idle 和 active 之间的更改(更改可能频繁且不太重要)外,所有更改都会得到通知。如果元数据是外部管理的,则会报告 active->active_idle。
- 清除
无设备,无容量,无级别
写入等同于 STOP_ARRAY ioctl
- inactive
可能有某些设置,但阵列未激活,所有 IO 均导致错误
写入时,不会销毁阵列,只是停止它
- suspended (尚未支持)
所有 IO 请求都将阻塞。可以重新配置阵列。
如果接受写入此项,将阻塞直到阵列进入静态(quiescent)
- readonly
无法进行同步。不写入超级块。
写请求失败
- read-auto
类似于 readonly,但在收到写请求时行为类似于
clean。- clean
没有挂起的写入,但处于活动状态。
当写入非活动阵列时,启动而不进行同步
如果写请求到达且元数据已知,则标记为
dirty并切换到active。如果未知,则阻塞并切换到 write-pending。如果写入有挂起写入的活动阵列,则会失败。
- active
完全活动:IO 和重新同步可能正在发生。当写入非活动阵列时,启动并进行同步
- write-pending
干净,但写入被阻塞等待写入
active。- active-idle
类似于 active,但有一段时间(safe_mode_delay)没有看到写入。
- consistency_policy
这指示阵列如何在意外关闭的情况下保持一致性。它可以是:
- 无
阵列没有冗余信息,例如 raid0, linear。
- resync
在不洁关闭后启动阵列时,将执行全量重新同步并重新生成所有冗余。
- bitmap
由写意图位图(write-intent bitmap)辅助的同步。
- journal
对于 raid4/5/6,日志设备用于记录事务并在不洁关闭后重放。
- ppl
仅针对 raid5,部分校验日志(Partial Parity Log)用于关闭写漏洞并消除重新同步。
写入此文件时接受的值为
ppl和resync,用于启用和禁用 PPL。- uuid
这以以下格式指示阵列的 UUID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- bitmap_type
[RW] 读取时,此文件将显示此阵列当前和可用的位图。当前活动的位图将包含在 [] 括号中。向此文件写入位图名称或 ID 将把此阵列的控制切换到该新位图。注意,禁止为已创建的阵列写入新位图。
- 无
无位图
- bitmap
默认的内部位图
- llbitmap
无锁(lockless)内部位图
如果 bitmap_type 不是 none,则在 md 设备 KOBJ_CHANGE 事件之后,将创建额外的位图属性 bitmap/xxx 或 llbitmap/xxx。
如果 bitmap_type 是 bitmap,则 md 设备还将包含:
- bitmap/location
这指示阵列的写意图位图存储在何处。
它可以是
none,file或[+-]N。file以后可能会扩展为file:/file/name。[+-]N表示距离元数据开始的扇区数。这在所有设备上都有备份。对于具有外部管理元数据的阵列,偏移量是从设备的起始位置开始计算的。
- bitmap/chunksize
将由单个位表示的块的大小(以字节为单位)。对于 RAID456,它是单个设备的一部分。对于 RAID10,它是阵列的一部分。对于 RAID1,两者皆是(结果相同)。
- bitmap/time_base
在寻找位图中的位以进行清除之间的时间(以秒为单位)。在当前的实现中,在已知所有覆盖的块都已同步后,位将在
time_base的 2 到 3 倍时间内被清除。- bitmap/backlog
当 write-mostly 设备在 RAID1 中处于活动状态时,对这些设备的写请求在后台进行——文件系统(或设备的其他使用者)不必等待它们。
backlog设置并发后台写入次数的限制。如果超过此限制,新的写入将变为同步。- bitmap/metadata
这可以是
internal或external。
internal是默认值,表示位图的元数据存储在分配空间的前 256 字节中,并由 md 模块管理。
external表示位图元数据在内核之外进行管理(即由某些用户空间程序管理)
- bitmap/can_clear
这可以是
true或false。如果为true,则当相应的块被认为已同步时,位图中的位将被清除。如果为false,位将永远不会被清除。如果阵列降级或在写入过程中阵列变为降级,此值将自动设置为false。当元数据在外部管理时,一旦阵列不再降级且此事实已记录在元数据中,应将其设置为 true。
如果 bitmap_type 是 llbitmap,则 md 设备还将包含:
- llbitmap/bits
只读,显示位图位的状态,以及每个值的数量。
- llbitmap/metadata
只读,显示位图元数据,包括 chunksize, chunkshift, chunks, offset 和 daemon_sleep。
- llbitmap/daemon_sleep
读写,触发守护进程函数以清除脏位的间隔时间(秒)。
- llbitmap/barrier_idle
读写,页面屏障闲置的时间(秒),表示页面中的脏位将被清除。
随着组件设备被添加到 md 阵列,它们会作为新目录出现在 md 目录中,命名如下:
dev-XXX
其中 XXX 是内核已知的设备名称,例如 hdb1。每个目录包含:
- block
指向 /sys/block 中块设备的符号链接,例如:
/sys/block/md0/md/dev-hdb1/block -> ../../../../block/hdb/hdb1- super
包含从该设备读取或写入该设备的超级块映像的文件。
- state
记录阵列中设备当前状态的文件,可以是以逗号分隔的列表,包含以下内容:
- faulty
设备由于检测到故障而被踢出活动使用,或者它有未确认的坏块
- in_sync
设备是阵列中完全同步的成员
- writemostly
除非没有其他选择,否则设备将只受制于读请求。
这仅适用于 raid1 阵列。
- blocked
设备已发生故障,且故障尚未被元数据处理器确认。
如果该设备不是故障设备,则本应写入该设备的写入将被阻塞。
- spare
设备正在工作,但不是正式成员。
这包括正在进行恢复操作的备用盘
- write_error
设备曾出现过写错误。
- want_replacement
设备(大部分)正常工作,但由于错误或用户请求,可能需要更换。
- replacement
设备是具有相同 raid_disk 的另一个活动设备的替代品。
此列表将来可能会增加。
此文件是可写的。
写入
faulty模拟设备上的故障。写入
remove将设备从阵列中移除。写入
writemostly设置 writemostly 标志。写入
-writemostly清除 writemostly 标志。写入
blocked设置blocked标志。写入
-blocked清除blocked标志,允许完成写入,并可能模拟一个错误。写入
in_sync设置 in_sync 标志。写入
write_error设置 writeerrorseen 标志。写入
-write_error清除 writeerrorseen 标志。允许随时写入
want_replacement,但不能写入替代设备或备用盘。它会设置该标志。允许随时写入
-want_replacement。它会清除该标志。仅允许在启动阵列之前写入
replacement或-replacement。它会设置或清除该标志。此文件响应 select/poll。对
faulty或blocked的任何更改都会引起一个事件。- errors
在该设备上检测到的读错误的近似计数,但未导致设备被逐出阵列(要么是因为它们已被纠正,要么是因为它们发生在阵列只读期间)。使用第 1 版元数据时,此值在阵列重启后仍然保持。
可以在组装阵列时写入此值,从而为元数据由用户空间管理的阵列提供持续计数。
- slot
这给出了设备在阵列中的角色。如果设备在阵列中不活跃(即是备用盘或已发生故障),它将为
none;或者是一个小于阵列raid_disks数量的整数,指示它当前填充的位置。这只能在组装阵列时设置。设置此项的设备被假定为工作正常的。- offset
这给出了设备中存储阵列数据的位置(从开始处计算的扇区数)。此偏移量之前的任何部分都不会被触及,除非它用于存储元数据(格式 1.1 和 1.2)。
- size
偏移量之后可用于存储数据的设备量。通常与 component_size 相同。这可以在组装阵列时写入。如果写入的值小于当前的 component_size,它将被拒绝。
- recovery_start
当设备不是
in_sync时,此项记录从设备起始位置开始已知正确的扇区数。这通常为零,但在恢复操作期间它会稳步增加,如果恢复中断,恢复此值可以使恢复避免重复前面的块。使用 v1.x 元数据,此值会自动保存和恢复。只要设备不是阵列的活动成员,无论是在激活阵列之前还是在设置
slot(插槽)之前,都可以设置此项。将其设置为
none等同于设置in_sync。设置为任何其他值也会清除in_sync标志。- bad_blocks
这以起始地址和长度(分别为扇区数)的形式给出了所有已知坏块的列表。如果输出太大而无法放入一个页面,它将被截断。向此文件写入
扇区号 长度会添加新的已确认(即已安全记录到磁盘)坏块。- unacknowledged_bad_blocks
这以
bad_blocks的相同形式给出了已知但尚未保存到磁盘的坏块列表。如果输出太大而无法放入一个页面,它将被截断。向此文件写入内容会添加坏块但不确认它们。这主要用于测试。- ppl_sector, ppl_size
此设备上用于部分校验日志(Partial Parity Log)的空间的位置和大小(以扇区为单位)。
活动的 md 设备还将包含阵列中每个活动设备的条目。这些被命名为:
rdNN
其中 NN 是阵列中的位置,从 0 开始。因此,对于 3 驱动器阵列,将会有 rd0, rd1, rd2。这些是到相应 dev-XXX 条目的符号链接。例如:
cat /sys/block/md*/md/rd*/state
每行都会显示 in_sync。
支持数据冗余的级别(1,4,5,6,10)的活动 md 设备还具有:
- sync_action
一个可用于监控和控制重建过程的文本文件。它包含一个单词,可以是以下之一:
- resync
在不洁关闭或创建后,正在重新计算冗余
- recover
正在构建热备用盘以替换故障/缺失的设备
- idle
什么都没发生
- check
已请求全量冗余检查且正在进行。这将读取所有块并进行检查。对于某些 raid 级别,也可能发生修复。
- repair
全量检查并修复正在进行。这类似于
resync,但是由用户请求的,并且不使用写意图位图来优化过程。此文件是可写的,且可以读取的每个字符串对于写入也都有意义。
idle将停止活动的 resync/recovery 等。不能保证另一个 resync/recovery 不会自动再次启动,尽管需要某些事件来触发它。
resync或recovery可用于重启由于idle停止的相应操作。如果当前状态为
idle,check和repair将启动相应的进程。此文件响应 select/poll。值的任何重要更改都会触发轮询事件。有时,如果似乎需要恢复但无法实现,值会短暂变为
recover。在这种情况下,不通知向recover的转换,但通知从其离开的转换。- degraded
这包含阵列降级的设备数量。因此,最佳阵列将显示
0。单个故障/缺失的驱动器将显示1,以此类推。此文件响应 select/poll,缺失设备数量的任何增加或减少都会触发一个事件。
- mismatch_count
在执行
check和repair,以及执行resync时,md 将计算发现的错误数量。mismatch_cnt中的计数是已重写或(对于check)本应重写的扇区数。由于大多数 raid 级别是以页面而非扇区为单位工作,这可能比实际错误数量大,因数是一个页面中的扇区数。- bitmap_set_bits
如果阵列有写意图位图,则写入此属性可以设置位图中的位,指示同步需要检查相应的块。可以写入单个数字或起止对。多个数字可以用空格分隔。
请注意,这些数字是
位(bit)编号,而不是块(block)编号。它们应按 bitmap_chunksize 进行缩放。- sync_speed_min, sync_speed_max
这些类似于
/proc/sys/dev/raid/speed_limit_{min,max},但它们仅适用于特定阵列。如果没有给这些文件写入任何值,或者写入了单词
system,则使用系统范围的值。如果写入一个以 KiB/s 为单位的值,则使用该值。读取文件时,它们会显示当前活动的值,后跟
(local)或(system),取决于它是本地设置的值还是系统范围的值。- sync_completed
这显示了当前 sync_action 已完成的扇区数,后跟可能需要处理的总扇区数。这两个数字由
/分隔,实际上显示为一个值,即已完成进度的比例。在此属性上的
select将在同步完成、达到当前的 sync_max(见下文)以及可能在其他时间返回。- sync_speed
这显示了当前 sync_action 的实际当前速度,单位为 KiB/sec。它是过去 30 秒内的平均值。
- suspend_lo, suspend_hi
这两个值以扇区数给出,指示阵列中将阻塞 IO 的范围。目前仅针对 raid4/5/6 提供支持。
- sync_min, sync_max
这两个值以扇区数给出,指示
check/repair操作的范围。必须是 chunk_size 的倍数。当达到sync_max时,它将暂停而不是完成。您可以在sync_completed上使用select或poll来等待该数字达到 sync_max。然后您可以增加sync_max,或者向sync_action写入idle。
sync_max的值为max有效地禁用了限制。当同步处于活动状态时,该值只能增加,不能减少。0是sync_min的最小值。
每个活动的 md 设备还可能具有管理它的 personality 模块所特有的属性。这些是模块实现的特有属性,如果实现发生更改,它们可能会发生实质性变化。
目前包括:
- stripe_cache_size (目前仅限 raid5)
带区缓存中的条目数。这是可写的,但有上限和下限(32768, 17)。默认值为 256。
- strip_cache_active (目前仅限 raid5)
带区缓存中的活动条目数
- preread_bypass_threshold (目前仅限 raid5)
需要预读的带区被不需要预读的带区绕过的次数。为了公平性,默认值为 1。将其设置为 0 会禁用绕过核算,并要求预读带区等待,直到所有全宽度带区写入完成。有效值为 0 到 stripe_cache_size。
- journal_mode (目前仅限 raid5)
raid5 的缓存模式。raid5 可以包含一个额外的磁盘用于缓存。模式可以是 “write-through” 或 “write-back”。默认值为 “write-through”。
- ppl_write_hint
为每个 PPL 写请求设置的 NVMe 流 ID。