Zoned Storage-Linux Kernel Support之总览

本文详细介绍了Linux内核对分区块设备的支持,包括文件和原始块访问接口,以及内核版本中逐步增加的功能。从4.10内核开始支持,后续版本增加了设备映射器支持和文件系统改进,如F2FS和zonefs。文章还讨论了ZBD支持的限制,如区域大小和读取限制,并强调了直接I/O在顺序写入中的重要性。

前言

Linux 内核通过具有不同访问特性的各种 I/O 路径支持分区存储设备,例如原始设备访问、文件系统和设备映射器目标。
从4.10 的 Linux® 内核中就开始支持分区块设备。 后续版本改进了这种支持,并在原始块设备访问接口之外添加了新功能。 现在可以使用更高级的功能,例如设备映射器支持和 ZBD 感知的文件系统。

概述

应用程序的开发人员可以通过各种不同的 I/O 路径来使用分区的块设备,可以通过不同的编程接口对其进行控制,并且可以以不同的方式公开分区块设备。 下图显示了各种访问路径的简化表示。
在这里插入图片描述
上图中有三个不同的 I/O 路径实现了两个 POSIX 兼容接口,这些接口隐藏了分区块设备的顺序区域的写入约束。 这三个 I/O 路径可以运行遗留应用程序(未修改以实现全顺序写入流的应用程序)。从左至右依次为:

文件访问接口

这是文件系统实现的接口,允许应用程序将其数据组织到文件和目录中。 文件访问接口有两种不同的实现:

  • ZBD 兼容文件系统:通过此实现,文件系统被修改为直接处理分区块设备的顺序写入约束。 应用程序对文件的随机写入被文件系统转换为顺序写入流,从而对应用程序隐藏了设备约束。 F2FS 文件系统就是一个例子。
  • Legacy File System:使用此实现,使用未修改的文件系统,并且设备顺序写入约束由设备映射器目标驱动程序处理,该驱动程序将分区块设备公开为常规块设备。 此设备映射器称为 dm-zoned。 它的特性和使用在the dm-zoned section of the “Device Mapper” guide “进行了详细讨论。

原始块访问接口

这是原始块设备文件访问接口,应用程序可以使用它直接访问存储在设备上的数据。 与遗留文件系统案例类似,此接口是使用 dm-zoned 设备映射器目标驱动程序实现的,以对应用程序隐藏顺序写入约束。

三个附加接口可用于已写入或修改以符合分区块设备的顺序写入约束的应用程序。 这些接口直接将设备约束暴露给应用程序,这些应用程序必须确保使用从区域的写入指针位置开始的顺序流写入数据。

1.文件访问接口:这个特殊的接口由 zonefs 文件系统实现。 zonefs 是一个非常简单的文件系统,它将分区块设备的每个区域公开为一个文件。 但与常规 POSIX 文件系统不同的是,zonefs 不会自动处理设备的顺序写入约束。 应用程序负责按顺序写入代表区域的文件。

2.分区原始块访问接口:这是 原始块访问接口 的对应物(没有任何中间驱动程序来处理设备约束)。 应用程序可以通过直接打开代表分区块设备的设备文件来使用此接口,以访问块层提供的区域信息和管理操作。 例如,Linux System Utilities 使用此接口。 物理分区块设备以及逻辑创建的分区块设备(例如,使用 dm-linear 设备映射器目标创建的分区块设备)支持此接口。 libzbd 用户库和工具可以简化使用此接口的应用程序的实现。

3.直通设备访问接口:这是允许应用程序将 SCSI 或 NVMe 命令直接发送到设备的接口(由 SCSI 通用驱动程序 (SG) 和 NVMe 驱动程序提供)。 内核对应用程序发送的命令的干扰最小,因此需要一个应用程序本身可以处理所有设备约束(例如逻辑和物理扇区大小、区域边界、命令超时、命令重试计数等)。 libzbclibnvme 等用户级库可以极大地简化使用该接口的应用程序的实现。

内核版本

带有内核 4.10 的分区块设备支持的初始版本仅限于块层 ZBD 用户界面、SCSI 层顺序写入顺序控制和对 F2FS 文件系统的本机支持。 以下内核版本添加了更多功能,例如设备映射器驱动程序和对块多队列基础架构的支持。
下图总结了分区块设备支持与内核版本的演变。
在这里插入图片描述

  • Passthrough Access Support (SG Access) 直通访问支持(SG 访问): 支持将主机管理的 ZBC/ZAC 硬盘公开为 SCSI 通用 (SG) 节点已正式添加到内核 3.18,其中定义了 SCSI 设备的设备类型 TYPE_SCSI 和 ATA 设备的设备类 ATA_DEV_ZAC 的定义。 对于 3.18 版本之前的内核,SATA 主机管理的 ZAC 磁盘不会作为 SG 节点或块设备文件向用户公开。 这些较旧的内核将简单地忽略报告主机管理的 ZAC 设备签名的 SATA 设备,并且这些设备将无法以任何方式使用。 对于连接到兼容 SAS HBA 的 SCSI 磁盘或 SATA 磁盘,用户可以通过 SG 驱动程序创建的节点文件访问主机管理的磁盘来表示这些磁盘。
  • Zoned Block Device Access and F2FS Support 分区块设备访问和 F2FS 支持:内核版本 4.10 添加的块 I/O 层分区块设备支持允许将主机管理的 ZBC 和 ZAC 磁盘公开为块设备文件,类似于常规磁盘。 此支持还包括对内核 libata 命令转换的更改,以将 SCSI ZBC 区域块命令转换为 ZAC 区域 ATA 命令。 对于依赖 SCSI 通用直接访问的应用程序,这可以使用相同的代码处理 ZBC (SCSI) 和 ZAC (ATA) 磁盘(例如,不需要发出 ATA 命令)。 使用带有常规 POSIX 系统调用的磁盘块设备文件(例如 /dev/sdX 设备文件)也可以访问分区块设备。 但是,与普通磁盘相比,仍然存在一些限制(请参阅ZBD Support Restrictions)。
  • Device Mapper and dm-zoned Support设备映射器和 dm-zoned 支持:在内核版本 4.13.0 中,设备映射器基础结构添加了对分区块设备的支持。 这种支持允许在分区块设备之上使用 dm-linear 和 dm-flakey 设备映射器目标。 此外,还添加了 dm 分区设备映射器目标驱动程序。
  • Block multi-queue and SCSI multi-queue Support块多队列和 SCSI 多队列支持:在内核版本 4.16.0 中,添加了对块多队列基础结构的支持。 此改进支持使用启用了 SCSI 多队列 (scsi-mq) 支持的主机管理的 ZBC 和 ZAC 磁盘,同时保留对传统单队列块 I/O 路径的支持。 块多队列和 scsi-mq I/O 路径是自内核版本 5.0 以来的默认设置,删除了旧的单队列块 I/O 路径支持。
  • zonefs:内核 5.6.0 首次引入了 zonefs 文件系统,它将分区块设备的区域公开为常规文件。 zonefs 使用内核内部分区块设备接口实现,支持所有类型的分区块设备(SCSI ZBC、ATA ZAC 和 NVMe ZNS)。
  • Zone Append Operation Support :内核版本 5.8.0 引入了一个通用块层接口,用于支持区域追加写入操作。 此版本还修改了 SCSI 层以使用常规写入命令模拟这些操作。 通过引入 NVMe ZNS 支持(见下文),该仿真统一了所有分区块设备的接口和功能,简化了文件系统等其他功能的实现。
  • NVM Express Zoned Namespaces:在内核版本 5.9 中,添加了对 NVMe ZNS 命令集的支持。 这使 nvme 驱动程序具有发现分区命名空间所需的命令集增强功能,并将它们注册到块层作为主机托管区域块设备。 此内核版本仅支持不实现任何区域可选特性 (ZOC) 的设备,并且还要求设备实现可选的区域附加命令。
  • btrfs :对内核分区块设备支持的改进仍在进行中。 新文件系统(例如 btrfs)

ZBD 支持限制

为了尽量减少对block层代码的更改,重用了块层的各种现有功能(例如,为软件 RAID 实现的 LBA 边界上的 IO 自动拆分就是这种重用的一个例子)。 与分区块设备的行为不兼容或太复杂而无法更改的内核组件保持不变。 这导致了一组约束,这些约束约束了所有与 Linux 一起工作的分区块设备。

  • 区域大小 ZBC、ZAC 和 ZNS 标准不对设备的区域布局施加任何限制(这意味着区域可以是任意大小),但内核 ZBD 支持仅限于所有区域大小相同的区域设备 . 区域大小还必须等于逻辑块的数量,即 2 的幂。只有设备的最后一个区域可能具有较小的大小(所谓的欠缺区域)。 此区域大小限制允许内核代码使用通常用于软件 RAID 设备的块层“分块”空间管理。 分块空间管理使用二次幂算术(位移操作)来确定正在访问哪个块(即哪个区域),并且它还确保块 I/O 操作不会跨越区域边界。
  • 无限制读取 ZBC 和 ZAC 标准定义了 URSWRZ 位,该位确定当读取操作针对顺序写入所需区域的未写入扇区时,设备是否会返回错误。 (这种读取操作的一个示例是当读取命令访问区域的写入指针位置之后的扇区时。)Linux 仅支持允许不受限制的读取命令的 ZBC 和 ZAC 主机管理的硬盘。 换句话说,Linux 仅支持报告未设置 URSWRZ 位的 SMR 硬盘。 添加此限制是为了确保在检查磁盘分区表时块层磁盘分区扫描过程不会导致读取命令失败。
  • 直接 IO 写入 内核页缓存不保证缓存的脏页将按扇区顺序刷新到块设备。 如果应用程序使用缓冲写入来写入设备的顺序写入所需区域,这可能会导致未对齐的写入错误。 为了避免这个陷阱,直接使用没有文件系统的分区块设备的应用程序应该始终使用直接 I/O 操作来写入主机管理磁盘的顺序写入所需区域(也就是说,它们应该发出 write() 系统 使用 O_DIRECT 标志的块设备“文件打开”调用)。
  • Zone Append ZNS 规范定义了可选的“Zone Append”命令。 当主机必须写入数据但要求设备报告数据放置的位置时,可以使用此命令代替常规写入命令。 这允许高效的主机实现,因为 (1) 不必跟踪写指针,并且 (2) 不必对写命令进行排序。 Linux IO 堆栈已启用以将其与内核版本 5.8 一起使用,并且 NVMe 驱动程序要求设备支持此可选命令,以便命名空间可通过内核使用。
### 关于 `dm-zoned` 的介绍 #### 设备映射器模块中的 `dm-zoned` 设备映射器(Device Mapper)是一个 Linux 内核框架,用于管理块设备的抽象层。它允许创建虚拟块设备,这些设备可以基于其他物理或逻辑块设备构建复杂的功能[^3]。 `dm-zoned` 是 Device Mapper 中的一个特定目标类型,旨在处理分区设备上的写入操作优化。对于现代大容量 SSD 和 HDD 存储介质而言,它们通常具有内部区域划分特性,即所谓的 Zoned Block Devices (ZBD),这使得某些部分只支持顺序写入而不能随机覆盖旧数据。为了更好地适应这种新型存储技术并提高性能,Linux 社区开发了 `dm-zoned` 来作为解决方案之一[^1]。 当使用 `dm-zoned` 时,会通过识别底层设备是否为分区分块设备来决定如何管理和调度 I/O 请求。如果检测到的是一个 zone-aware 或者 zoned 型态的目标,则该驱动程序将会按照相应的规则执行读/写命令序列化控制以及重定位等动作以确保最佳效率。 此外,在初始化过程中,`dm-init()` 函数负责启动整个 Device Mapper 模块,并调用一系列必要的子功能完成设置工作;而对于具体像 `dm-zoned` 这样的组件来说,其配置参数可能涉及到指定哪些实际磁盘应当被当作带状结构看待等问题。 ```c // Example of initializing a dm-zoned target within the kernel code. static int __init dm_zoned_init(void) { // Initialization logic here... } module_init(dm_zoned_init); ``` #### 数据结构关联 在实现上,`dm-zoned` 需要依赖一些核心的数据结构来进行有效的资源管理和请求转发。例如: - **struct dm_dev**: 描述了一个低级别的块设备实例,包含了指向底层 block_device 结构体的指针以及其他元信息,如文件访问权限和名称等属性。 - **set_capacity()**: 此函数用来设定给定通用磁盘对象 (`gendisk`) 所表示的实际大小,这对于正确反映新加入系统的分区或者调整现有卷尺寸非常重要[^2]。 综上所述,`dm-zoned` 提供了一种机制让操作系统能够充分利用带有内置区域特性的现代化固态硬盘和其他类型的持久性内存装置所带来的优势。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值