RAID 阵列

启动时组装 RAID 阵列

管理 md 设备的工具可以在以下位置找到

https://linuxkernel.org.cn/pub/linux/utils/raid/

您可以使用以下内核命令行来启动您的 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 设备 编号。

md 设备的编号

md 设备 编号。

设备

0

md0

1

md1

2

md2

3

md3

4

md4

raid 级别

RAID 阵列的级别

raid 级别

级别

-1

线性模式

0

条带模式

其他模式仅在具有持久超级块的情况下才支持

大小 因子

(仅 raid-0 和 raid-1)

将块大小设置为 4k << n。

故障 级别

完全忽略

dev0devn

例如 /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 意味着奇偶校验不可信,并且它是降级的意味着一些数据块丢失并且无法可靠地重建(由于没有奇偶校验)。

因此,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 从阵列中分离已失败或尚未激活的设备。

适用于 format-0 超级块阵列和没有超级块的阵列(非持久)的特定规则

可以通过在 SET_ARRAY_INFO ioctl 中描述阵列(级别、块大小等)来 创建 阵列。 这必须具有 major_version==0raid_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 设备都包含

级别

一个文本文件,指示 raid 级别。 例如,raid0、raid1、raid5、linear、multipath、faulty。 如果尚未设置 raid 级别(阵列仍在组装中),则该值将反映已写入它的内容,这可能是像上面这样的名称,也可能是一个数字,例如 05 等。

raid_disks

一个文本文件,其中包含一个简单的数字,指示完全功能的阵列中的设备数量。 如果这还未知,则该文件将为空。 如果正在调整阵列的大小,这将包含新的设备数量。 某些 raid 级别允许在阵列处于活动状态时设置此值。 这将重新配置阵列。 否则,只能在组装阵列时设置它。 如果更改此属性会减小阵列的大小,则不允许更改。 要减少例如 raid5 中的驱动器数量,必须首先通过设置 array_size 属性来减小阵列大小。

chunk_size

这是 的大小(以字节为单位),并且仅与涉及条带化的 raid 级别 (0,4,5,6,10) 相关。 阵列的地址空间在概念上分为块,连续的块被条带化到相邻的设备上。 大小应至少为 PAGE_SIZE (4k),并且应为 2 的幂。 只能在组装阵列时设置此值

layout

特定级别的阵列的 layout。 这只是一个数字,由不同的级别以不同的方式解释。 可以在组装阵列时写入它。

array_size

这可以用于人为地限制阵列中的可用空间小于组合设备上实际可用的空间。 写入小于可用大小的数字(以千字节为单位)将设置大小。 阵列的任何重新配置(例如,添加设备)都不会导致大小发生变化。 写入单词 default 将导致阵列的有效大小是基于 levelchunk_sizecomponent_size 实际可用的任何大小。

这可用于在减少 raid4/5/6 中的设备数量之前减小阵列的大小,或支持强制执行此类裁剪的外部元数据格式。

reshape_position

这是 none 或阵列设备中的一个扇区号,其中 reshape 达到了。 如果设置了此项,则上面提到的三个属性(raid_disks、chunk_size、layout)可能具有 2 个值,一个旧值和一个新值。 如果这些值不同,则读取该属性会返回

new (old)

写入将影响 new 值,而使 old 值保持不变。

component_size

对于具有数据冗余的阵列(即,不是 raid0、linear、faulty、multipath),所有组件的大小必须相同 - 或者至少必须有一个它们都提供空间的尺寸。 这是阵列几何形状的关键部分。 它以扇区为单位测量,可以从此处读取。 如果特性支持(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。 这被称为 safe_modecertain period 由此文件控制,该文件将该周期存储为秒数。 默认值为 200 毫秒 (0.200)。 写入 0 值会禁用安全模式。

array_state

此文件包含一个单词,描述了阵列的当前状态。 在许多情况下,可以通过写入所需状态的单词来设置状态,但是某些状态无法显式设置,并且不允许某些转换。

Select/poll 在此文件上工作。 除了 Active_idle 和 active 之间的所有更改(这可能是频繁的并且不是很令人感兴趣)都会收到通知。 如果元数据是外部管理的,则报告 active->active_idle。

clear

没有设备,没有大小,没有级别

写入等同于 STOP_ARRAY ioctl

inactive

可能有一些设置,但阵列未处于活动状态,所有 IO 都会导致错误

写入时,不会拆除阵列,而只是停止它

suspended(尚不支持)

所有 IO 请求都将被阻止。 可以重新配置阵列。

写入此内容(如果被接受)将阻止,直到阵列处于静止状态

readonly

不会发生重新同步。 不会写入超级块。

写入请求失败

read-auto

像 readonly 一样,但在写入请求时表现得像 clean

clean

没有挂起的写入,但在其他方面处于活动状态。

当写入到非活动阵列时,启动时不进行重新同步

如果到达写入请求,则如果元数据已知,则标记为 dirty 并切换到 active。 如果未知,则阻止并切换到 write-pending

如果写入到具有挂起写入的活动阵列,则失败。

active

完全活动:IO 和重新同步可能正在发生。 当写入到非活动阵列时,启动时进行重新同步

write-pending

clean,但写入被阻止,等待写入 active

active-idle

像 active 一样,但一段时间内(safe_mode_delay)没有看到写入。

bitmap/location

这指示了阵列的写入意图位图的存储位置。

它可以是 nonefile[+-]N 之一。 file 稍后可能会扩展为 file:/file/name [+-]N 意味着从元数据开始的许多扇区。

这在所有设备上都复制。 对于具有外部管理的元数据的阵列,偏移量是从设备开始计算的。

bitmap/chunksize

将由单个位表示的块的大小(以字节为单位)。 对于 RAID456,它是单个设备的一部分。 对于 RAID10,它是阵列的一部分。 对于 RAID1,两者都是(它们的意思相同)。

bitmap/time_base

在位图中查找要清除的位之间的时间(以秒为单位)。 在当前的实现中,在一个位被覆盖的所有块已知同步后,该位将在 2 到 3 倍的 time_base 之间被清除。

bitmap/backlog

当 write-mostly 设备在 RAID1 中处于活动状态时,对这些设备的写入请求在后台进行 - 文件系统(或设备的其他用户)不必等待它们。 backlog 设置了并发后台写入次数的限制。 如果超过此数量,则新的写入将是同步的。

bitmap/metadata

这可以是 internalexternal

internal

是默认值,表示位图的元数据存储在分配空间的前 256 个字节中,并由 md 模块管理。

external

表示位图元数据在内核外部管理(即,由某些用户空间程序)。

bitmap/can_clear

这可以是 truefalse。 如果 true,则当认为相应的块已同步时,位图中的位将被清除。 如果 false,则位将永远不会被清除。 如果在降级的阵列上发生写入,或者阵列在写入期间变为降级,则会自动将其设置为 false。 当元数据在外部管理时,一旦阵列变为非降级,就应将其设置为 true,并且此事实已记录在元数据中。

consistency_policy

这指示阵列如何在意外关闭的情况下保持一致性。 它可以是

none

阵列没有冗余信息,例如 raid0、linear。

resync

执行完全重新同步,并在不干净关闭后启动阵列时重新生成所有冗余。

bitmap

由写入意图位图辅助的重新同步。

journal

对于 raid4/5/6,使用日志设备来记录事务并在不干净关闭后重播。

ppl

仅对于 raid5,部分奇偶校验日志用于关闭写入孔并消除重新同步。

写入此文件时接受的值为 pplresync,用于启用和禁用 PPL。

uuid

这指示阵列的 UUID,格式如下:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

当组件设备添加到 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。对 faultyblocked 的任何更改都会导致事件。

errors (错误)

在此设备上检测到的读取错误的近似计数,这些错误尚未导致设备从阵列中移除(要么是因为它们已被纠正,要么是因为它们发生在阵列处于只读状态时)。当使用 version-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 (坏块)

这给出了所有已知坏块的列表,形式为起始地址和长度(分别以扇区为单位)。如果输出太大而无法容纳在一个页面中,它将被截断。将 sector length 写入此文件会添加新的已确认(即安全地记录到磁盘)的坏块。

unacknowledged_bad_blocks (未确认的坏块)

这给出了已知但尚未保存到磁盘的坏块的列表,形式与 bad_blocks 相同。如果输出太大而无法容纳在一个页面中,它将被截断。写入此文件会添加坏块而不确认它们。这主要用于测试。

ppl_sector, ppl_size

用于此设备上部分奇偶校验日志的空间的位置和大小(以扇区为单位)。

活动的 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

resync

recover (恢复)

正在构建热备盘以替换故障/缺失设备

idle (空闲)

没有任何事情发生

check (检查)

已请求并正在进行冗余的全面检查。这将读取所有块并检查它们。对于某些 raid 级别,也可能发生修复。

repair (修复)

正在进行全面检查和修复。这类似于 resync,但由用户请求,并且未使用写入意图位图来优化该过程。

此文件是可写的,并且可以读取的每个字符串对于写入都有意义。

idle 将停止活动的 resync/recovery 等。不能保证不会自动再次启动另一个 resync/recovery,但需要一些事件来触发它。

如果使用 idle 停止了 resyncrecovery,则可以使用它们来重新启动相应的操作。

如果当前状态为 idlecheckrepair 将启动相应的过程。

此文件响应 select/poll。该值中的任何重要更改都会触发 poll 事件。有时,如果似乎需要恢复但无法实现,则该值会短暂地变为 recover。在这种情况下,不会通知到 recover 的转换,但会通知离开的转换。

degraded (降级)

这包含阵列降级的设备数量的计数。因此,一个最佳阵列将显示 0。单个故障/缺失的驱动器将显示 1,等等。

此文件响应 select/poll,缺失设备数量的任何增加或减少都会触发一个事件。

mismatch_count (不匹配计数)

当执行 checkrepair 时,以及可能在执行 resync 时,md 将计算发现的错误数量。mismatch_cnt 中的计数是已重新写入的扇区数,或者(对于 check)本应重新写入的扇区数。由于大多数 raid 级别以页而不是扇区为单位工作,因此这可能比实际错误数大一个因子,该因子是页面中的扇区数。

bitmap_set_bits (位图设置位)

如果阵列具有写入意图位图,则写入此属性可以设置位图中的位,表明 resync 需要检查相应的块。可以写入单个数字或起始-结束对。多个数字可以用空格分隔。

请注意,这些数字是 bit 数字,而不是 block 数字。它们应该按 bitmap_chunksize 缩放。

sync_speed_min, sync_speed_max

这些与 /proc/sys/dev/raid/speed_limit_{min,max} 类似,但它们仅适用于特定的阵列。

如果未向这些写入任何值,或者写入单词 system,则使用系统范围的值。如果写入一个值(以千字节/秒为单位),则使用该值。

读取文件时,它们会显示当前活动值,后跟 (local)(system),具体取决于它是本地设置的值还是系统范围的值。

sync_completed (同步完成)

这显示了当前 sync_action 已完成的扇区数,后跟可能需要处理的总扇区数。这两个数字用 / 分隔,从而有效地显示一个值,即已完成的进程的一小部分。

当 resync 完成时,当它达到当前的 sync_max(如下)时,并且可能在其他时间,在此属性上的 select 将返回。

sync_speed (同步速度)

这显示了当前 sync_action 的当前实际速度,以 K/秒为单位。它在过去 30 秒内平均。

suspend_lo, suspend_hi (挂起下限,挂起上限)

这两个值以扇区数为单位给出,表示阵列中 IO 将被阻止的范围。目前仅支持 raid4/5/6。

sync_min, sync_max (同步下限,同步上限)

这两个值以扇区数为单位给出,表示阵列中 check/repair 将运行的范围。必须是 chunk_size 的倍数。当它达到 sync_max 时,它将暂停,而不是完成。您可以使用 selectpollsync_completed 上等待该数字达到 sync_max。然后,您可以增加 sync_max,或者可以将 idle 写入 sync_action

sync_maxmax 值有效地禁用了该限制。当 resync 处于活动状态时,该值只能增加,永远不能减少。sync_min 的最小值为 0

每个活动的 md 设备也可能具有特定于管理它的个性的模块的属性。这些属性特定于模块的实现,如果实现发生变化,则可能会发生重大变化。

这些目前包括

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-throuth”和“write-back”。默认值为“write-through”。(直写和回写)

ppl_write_hint

为每个 PPL 写入请求设置的 NVMe 流 ID。