Zoned Storage-Linux Kernel Support 之 用户接口
分区块设备用户接口
用户应用程序可以使用两种类型的接口来访问分区块设备的区域信息和管理分区块设备的区域。 这两种类型的接口是:
- sysfs 属性文件,可以直接从应用程序作为常规文件访问,也可以从脚本语言(shell 脚本、python 等)访问。
- ioctl() 系统调用,适用于 C 程序或其他具有等效系统调用绑定的编程语言。
自内核 4.10 中引入分区块设备支持以来,应用程序可用的 sysfs 文件和 ioctl() 命令已经发展。 以下部分详细介绍了每个内核版本的文件和命令的可用性
Sysfs Interface
使用脚本语言(例如 bash 脚本)的程序可以通过 sysfs 属性文件访问分区设备信息。 这些属性文件如下
-
Device Zoned Model 设备分区模型
分区设备的区域模型可以通过zoned
设备队列属性文件发现。 例如:对于名为 sdb 的分区块设备,以下 shell 命令显示设备分区模型。# cat /sys/block/sdb/queue/zoned host-managed
分区属性文件的可能值如下表所示:
none 常规块设备,包括驱动器管理的 SMR 磁盘 host-aware 主机感知设备模型 host-managed 主机管理的设备模型
-
Zone Size区域大小
设备区域大小可以从名为chunk_sectors
的 sysfs 队列属性文件中读取。 对于名为 sdb 的设备(与前面示例中的设备相同),以下命令给出设备区域大小。# cat /sys/block/sdb/queue/chunk_sectors 524288
无论设备的实际逻辑和物理块大小如何,该值都显示为 512B 扇区的数量。 在此示例中,设备区域大小为 524288 x 512 = 256 MiB。
-
Number of Zones 区域数
sysfs 队列属性文件nr_zones
在 Linux 内核版本 4.20.0 中引入,可用于获取分区设备的区域总数# cat /sys/block/sdb/queue/nr_zones 55880
对于常规块设备,此属性值始终为 0。
-
Zone Resources 区域资源
可以从名为max_open_zones
和max_active_zones
的 sysfs 队列属性文件中读取设备区域资源。
对于名为 sdb 的 SAS 或 SATA 主机管理的 SMR 磁盘(与上一个示例中的设备相同),以下命令给出了可以处于隐式或显式打开状态的最大区域数。# cat /sys/block/sdb/queue/max_open_zones 128
该值显示为区域数,0 表示设备对可打开的最大区域数没有任何限制。
对于同一设备,以下命令给出了可以处于活动状态(打开或关闭状态)的最大区域数。# cat /sys/block/sdb/queue/max_active_zones 0
该值显示为多个区域,其中 0 表示设备对活动区域的最大数量没有任何限制。 对于 SMR 硬盘,此限制始终为 0。
这些属性公布的值因设备而异。 下面显示了一个使用 NVMe ZNS 设备的示例。
# cat /sys/block/nvme0n1/queue/max_open_zones 14 # cat /sys/block/nvme0n1/queue/max_active_zones 14
当使用 null_blk、QEMU 或 tcmu-runner 模拟分区设备时,可以手动配置这些属性的值以模拟不同的物理设备特性。
ioctl() Application Programming Interface
C 头文件 /usr/include/linux/blkzoned.h 包含宏定义和数据结构定义,允许应用程序开发人员获取有关分区块设备的信息并管理设备的区域。
- Zone Information Data Structures 区域信息数据结构
数据结构struct blk_zone
定义了一个zone-descriptor
结构,其中包含一个 zone 的完整描述:这包括 zone 在设备上的位置、zone 类型、它的条件(状态)和 zone 写指针的位置(用于顺序 区)。 对于内核 直到内核版本 5.8,这个数据结构如下图所示。
/**
* struct blk_zone - Zone descriptor for BLKREPORTZONE ioctl.
*
* @start: Zone start in 512 B sector units
* @len: Zone length in 512 B sector units
* @wp: Zone write pointer location in 512 B sector units
* @type: see enum blk_zone_type for possible values
* @cond: see enum blk_zone_cond for possible values
* @non_seq: Flag indicating that the zone is using non-sequential resources
* (for host-aware zoned block devices only).
* @reset: Flag indicating that a zone reset is recommended.
* @reserved: Padding to 64 B to match the ZBC/ZAC defined zone descriptor size.
*
* start, len, capacity and wp use the regular 512 B sector unit, regardless
* of the device logical block size. The overall structure size is 64 B to
* match the size of the ZBC-, ZAC- and ZNS-defined zone descriptor and to
* allow support for future additional zone information.
*/
struct blk_zone {
__u64 start; /* Zone start sector */
__u64 len; /* Zone length in number of sectors */
__u64 wp; /* Zone write pointer position */
__u8 type; /* Zone type */
__u8 cond; /* Zone condition */
__u8 non_seq; /* Non-sequential write resources active */
__u8 reset; /* Reset write pointer recommended */
__u8 reserved[36];
};
如对该数据结构定义的注释中所示,用于指示
(1) 区域起始位置、(2) 区域大小和 (3) 写指针位置的单位是“512B 扇区大小”。 无论设备的实际逻辑块大小如何,这都是正确的。 即使对于具有 4KB 逻辑扇区的设备,上述区域描述符字段也使用 512 字节的扇区大小单位。
在内核版本 5.9 中将容量字段添加到 struct blk_zone
。在内核版本 5.9 及更高版本(包含容量字段)中,数据结构如下。
/**
* struct blk_zone - Zone descriptor for BLKREPORTZONE ioctl.
*
* @start: Zone start in 512 B sector units
* @len: Zone length in 512 B sector units
* @wp: Zone write pointer location in 512 B sector units
* @type: see enum blk_zone_type for possible values
* @cond: see enum blk_zone_cond for possible values
* @non_seq: Flag indicating that the zone is using non-sequential resources
* (for host-aware zoned block devices only).
* @reset: Flag indicating that a zone reset is recommended.
* @resv: Padding for 8B alignment.
* @capacity: Zone usable capacity in 512 B sector units
* @reserved: Padding to 64 B to match the ZBC, ZAC and ZNS defined zone
* descriptor size.
*
* start, len, capacity and wp use the regular 512 B sector unit, regardless
* of the device logical block size. The overall structure size is 64 B to
* match the ZBC, ZAC and ZNS defined zone descriptor and allow support for
* future additional zone information.
*/
struct blk_zone {
__u64 start; /* Zone start sector */
__u64 len;