Zoned Storage-Linux Kernel Support 之 设备映射器

设备映射器Device Mapper在Linux内核4.13版开始支持分区块设备,包括dm-linear、dm-flakey和dm-zoned目标。dm-linear创建分区块设备,dm-flakey模拟设备错误,dm-zoned为非原生支持分区设备提供随机写入。dm-zoned通过元数据和写入缓冲方案处理顺序写入约束,允许文件系统和应用在无本机分区支持下使用分区设备。

设备映射器Device Mapper

首先需要明确的是设备映射器是工作在block级别而不是file级别的。
分区块设备支持已添加到内核版本 4.13 中的设备映射器子系统中。 两个现有的目标获得了支持:dm-linear 目标和 dm-flakey 目标。 ZBD 支持还添加了一个新的目标驱动程序,dm-zoned

dm-linear

dm-linear 目标将设备映射器设备的线性范围的blocks映射到后端设备上的线性范围。 dm-linear 是 LVM 等逻辑卷管理器的基本构建块。

Zoned Block Device Restrictions 分区块设备限制

当与分区块设备一起使用时,创建的 dm-linear 设备也将是分区块设备,其区域大小与底层设备相同。 在创建 dm-linear 目标设备期间,设备映射器核心管理代码会强制执行几个条件。
- 用于映射目标设备不同范围的所有后端设备必须具有相同的区域模型。
- 如果后端设备是分区块设备,则所有设备必须具有相同的区域大小。
- 映射的范围必须是区域对齐的,也就是说,部分区域映射是不可能的。

示例:创建一个小型Host Managed Disk

此示例说明如何从大型高容量主机托管磁盘创建使用区域范围的小型Host Managed 磁盘。 使用的后端设备的区域信息如下所示:

# cat /sys/block/sdb/queue/zoned
host-managed
# cat /sys/block/sdb/queue/chunk_sectors
524288
# blkzone report /dev/sdb
  start: 0x000000000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000080000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000100000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000180000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  ...
  start: 0x010580000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x010600000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x010680000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x010700000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  ...
  start: 0x6d2300000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x6d2380000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]

接下来,要创建一个名为“small-sdb”的 dm-linear 设备,它将后端设备的前 5 个常规区域(5*524288=2621440)与前 10 个连续区域连接起来,请使用以下命令。

# echo "0 2621440 linear /dev/sdb 0
2621440 5242880 linear /dev/sdb 274726912" | dmsetup create small-sdb

生成的设备区域模型是主机管理的,有 15 个区域,如下所示。

# cat /sys/block/dm-0/queue/zoned
host-managed
# cat /sys/block/dm-0/queue/chunk_sectors
524288
# blkzone report /dev/dm-0
  start: 0x000000000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000080000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000100000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000180000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000200000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000280000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000300000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000380000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000400000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000480000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000500000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000580000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000600000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000680000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]
  start: 0x000700000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 1(em) [type: 2(SEQ_WRITE_REQUIRED)]

下面显示了一个脚本,该脚本有助于使用来自单个分区块设备的区域范围创建 dm-linear 设备。 这种小的分区块设备可用于测试应用程序限制(例如磁盘已满情况)。

#!/bin/bash

if [ $# -ne 3 ]; then
    echo "Usage: $0 <disk> <num conv zones> <num seq zones>"
    exit 1
fi

disk="$1"
nrconv=$2
nrseq=$3
dname="$(basename ${disk})"

# Linear table entries: "start length linear device offset"
# start: starting block in virtual device
# length: length of this segment
# device: block device, referenced by the device name or by major:minor
# offset: starting offset of the mapping on the device

convlen=$(( nrconv * 524288 ))
seqlen=$(( nrseq * 524288 ))

if [ ${convlen} -eq 0 ] && [ ${seqlen} -eq 0 ]; then
    echo "0 zones..."
    exit 1
fi

seqofst=$(blkzone report "$1" | grep "SEQ_WRITE_REQUIRED" |
      head -n1 | cut -f1 -d',' | cut -f2 -d':' | xargs printf "%d\n")

if [ ${convlen} -gt ${seqofst} ]; then
    nrconv=$(( seqofst / 524288 ))
    echo "Too many conventional zones requested: truncating to $nrconv"
    convlen=${seqofst}
fi

if [ ${convlen} -eq 0 ]; then
    echo "0 ${seqlen} linear ${disk} ${seqofst}" | dmsetup create small-${dname}
elif [ ${seqlen} -eq 0 ]; then
    echo "0 ${convlen} linear ${disk} 0" | dmsetup create small-${dname}
else
    echo "0 ${convlen} linear ${disk} 0
    ${convlen} ${seqlen} linear ${disk} ${seqofst}" | dmsetup create small-${dname}
fi

示例:常规区域作为常规磁盘

dm-linear 还可用于将分区块设备的conventional zones常规区聚合到一个目标设备中,该设备可用作常规磁盘(常规区域可以随机写入)。 重复使用前面的示例后端磁盘,可以使用 524 个 524288 个扇区(512 B 单位)的常规区域。 以下命令创建一个将所有常规区域连接在一起的 dm-linear 设备。

# echo "0 274726912 linear /dev/sdb 0" | dmsetup create small-sdb

目标设备同样是主机管理的磁盘,但仅包含常规区域。

# cat /sys/block/dm-0/queue/zoned
host-managed
# cat /sys/block/dm-0/queue/chunk_sectors
524288
# blkzone report /dev/dm-0
  start: 0x000000000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000080000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000100000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x000180000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  ...
  start: 0x010500000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]
  start: 0x010580000, len 0x080000, wptr 0x000000 reset:0 non-seq:0, zcond: 0(nw) [type: 1(CONVENTIONAL)]

因为这个分区块设备完全由常规区域组成,所以所有扇区都是随机可写的,因此可以直接与任何文件系统一起使用。

# mkfs.ext4 /dev/dm-0
mke2fs 1.44.6 (5-Mar-2019)
Creating filesystem with 34340864 4k blocks and 8585216 inodes
Filesystem UUID: 3957429a-5dab-4b30-9797-f9736036a47b
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

# mount /dev/dm-0 /mnt
# ls -l /mnt
total 16
drwx------ 2 root root 16384 May 21 17:03 lost+found

需要频繁随机更新其元数据的应用程序可以使用此类设置来促进复杂元数据结构的实现。 应用程序可以直接使用磁盘的其余顺序区域来存储数据。

dm-flakey

dm-flakey 目标类似于 dm-linear 目标,只是它周期性地表现出不可靠的行为。 此目标对于在测试期间模拟故障设备很有用。 在分区块设备的情况下,模拟对顺序区域的写入错误可以帮助调试应用程序写入指针管理。

dm-flakey 的工作方式如下:在加载表时,设备在几秒钟内(正常运行时间)不会产生错误,但随后在几秒钟内表现出不可靠的行为。 然后重复这个循环。

Error modes 错误模式

可以配置几种错误模拟行为。

  • drop_writes 所有写入 I/O 都会被静默忽略并丢弃。 正确处理读取 I/O。
  • error_writes 所有写 I/O 都失败并发出错误信号。 正确处理读取 I/O。
  • crupt_bio_byte 在停机期间,将每个读或写块 I/O 的数据的第 N 字节替换为指定值。

默认错误模式是在仿真周期的停机时间内使所有 I/O 请求失败。

Zoned Block Device 限制

同样的限制适用于 dm-linear 目标。

dm-zoned

dm-zoned 设备映射器目标提供对zoned block 设备(ZBC 和 ZAC 兼容设备)的随机写入访问。 它对设备用户隐藏了主机管理的分区块设备的顺序写入约束(“设备用户”,在这种情况下,是文件系统或访问原始块设备的应用程序)。 这允许使用不具有本机zoned块设备支持的应用程序和文件系统。

可以本机支持主机管理的分区块设备的文件系统或应用程序(例如,自内核 4.10 以来的 f2fs 文件系统)不需要使用 dm-zoned 设备映射器目标。

设计概述

dm-zoned 实现了一个磁盘写入缓冲方案来处理对zoned块设备的顺序写入所需zoned的随机写入访问。 后端设备的常规区域用于缓冲随机访问以及存储内部元数据。
下图说明了 dm-zoned 区域使用原则。
在这里插入图片描述
从 Linux 内核版本 5.8.0 开始,可以使用额外的常规块设备来提供随机可写存储,取代后端分区块设备的常规区域用于写入缓冲。 有了这个新版本的 dm-zoned,还可以使用多个分区块设备来提高性能。

用于支持 dm-zoned 目标的设备的所有区域分为 2 种类型:

1.元数据区域 这些是用于存储元数据的随机可写区域。 随机可写区域可以是常规区域或顺序写入首选区域(仅限主机感知设备)。 元数据区域不会向用户报告为可用容量。 如果额外的常规块设备用于写入缓冲,则元数据区域将存储在此缓存设备上。
2.数据区域 设备的所有剩余区域。 这些区域中的大多数是顺序区域,专门用于存储用户数据。 常规区域(或主机感知设备上的顺序写入首选区域的一部分)也可用于缓冲用户随机写入。 因此,用户数据可以存储在常规区域或顺序区域中。

如上图所示,目标设备被划分为与后备分区设备的区域大小相同的块。 可以以不同方式将逻辑块映射到支持设备的区域。

1.常规或缓存区映射 图中的chunk A就是这种情况,它被映射到常规区CA。 这是在向空(未写入)块发出第一个写入命令时初始化的默认映射。 只要将一个块映射到常规区域,任何传入的写入请求都可以使用映射的常规区域直接执行。

2.顺序区域映射 一个块最初可以映射到一个顺序区域,如块 C 所示(映射到图中的顺序区域 SC)。 通过这样的映射,不能直接修改块的已写入块。 为了处理这种情况,使用下一个映射类型。

3.双常规-顺序区域映射 当您需要更新已映射到顺序区域的块的已写入块中的数据时,临时将常规区域添加到块映射中。 任何以写入块为目标的写入都将使用常规区域而不是顺序区域进行处理。

dm-zoned 元数据包括一组位图,用于跟踪支持设备区域中块的有效性状态。 任何写操作执行后总是更新位图,以将写入的块标记为有效。 在双重常规-顺序块映射的情况下,顺序区的块的位图被更新以清除表示已经用常规区中的写入更新的块的位。 通过这样做,传入的读取总是可以通过检查块有效性位图来访问最新版本的块数据。

磁盘格式

dm-zoned 公开一个扇区大小为 4096 字节的逻辑设备,而不管用作后端的分区块设备的物理扇区大小如何。 这减少了管理有效块(写入的块)所需的元数据量。 磁盘元数据格式如下:

1.超级块:找到的第一个随机可写区域的第一个块包含超级块,它描述了元数据块的数量和位置(在磁盘上)。
2.映射表块:在超级块之后,有一组块来描述(1)目标逻辑设备的逻辑块到(2)数据区的映射。 该映射以逻辑块编号为索引,每个映射条目表示存储该块数据的数据区。 它还可以指示用于缓冲对块数据的随机修改的随机区域的区域编号。
3.位图存储块:在映射表块之后,有一组块用于存储位图,指示数据区中块的有效性。 有效块是已写入且未丢弃的任何块。 在缓冲数据区中,一个块只能(1)在数据区或(2)在缓冲区有效

设备映射器子系统使用两组元数据区域,以保护内部元数据在突然断电或系统崩溃的情况下免受损坏。 一组(主要集)用作主要元数据集。 另一组(辅助集)用作日志。 修改后的元数据首先写入辅助集。 通过写入辅助集创建的日志通过在辅助集中写入更新的超级块来验证。 此日志操作完成后,将更新主要元数据集。 这可确保其中一组始终正确。

刷新操作用作提交点:当接收到刷新操作时,元数据活动暂时停止,所有脏元数据都被记录并更新,然后恢复正常操作。 刷新操作会暂时延迟写入请求并丢弃请求。 执行元数据记录时可以处理读取请求。

读写处理

在映射到随机data zone的逻辑块中,所有写入操作都是通过直接写入data zones来处理的。 如果映射区域映射到顺序区域,则仅当逻辑块内的写偏移量等于顺序数据区域内的写指针偏移量(即写操作与zone写指针对齐)时,才直接处理写操作 )。 否则,使用缓冲区间接处理写操作:分配一个随机可写的空闲数据区,并分配给除了已映射的顺序数据区之外正在访问的块。 将块写入缓冲区将使顺序数据区中的相同块无效。

读取操作根据位图提供的块有效性信息进行处理:从数据区读取有效块,或者如果数据区被缓冲,则从分配给数据区的缓冲区读取。

随机区回收

一段时间后,有限数量的可用随机区域可能会用完,从而无法对未缓冲区域进行未对齐的写入。 为了避免这种情况,回收进程定期扫描使用的随机区域,并尝试通过(顺序)将缓冲区的有效块复制到空闲的顺序区域来“回收”它们。 复制完成后,块映射将更新为指向顺序区域,并释放缓冲区以供重用。

用户空间工具

dmzadm 命令行实用程序用于格式化后端分区设备,以便与 d​​m-zoned 设备映射器目标一起使用。 此实用程序验证设备区域模型,并根据设备的容量和区域大小准备和写入磁盘上的 dm-zoned 元数据。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值