首页
/ Linux 内核 dm-zoned 完全指南:在 Device Mapper 层将分区块设备包装为普通块设备

Linux 内核 dm-zoned 完全指南:在 Device Mapper 层将分区块设备包装为普通块设备

2026-09-07 14:16:10作者:余洋婵Anita

dm-zoned 是 Linux 内核 Device Mapper 框架下的一个 target,它把底层符合 ZBC(SCSI)或 ZAC(ATA)规范的分区块设备(zoned block device)透明地包装成一个不受任何写模式约束的常规块设备,供文件系统或直接访问块设备的应用直接使用。本文以官方文档 Documentation/admin-guide/device-mapper/dm-zoned.rst 为骨架,结合本仓库 drivers/md/ 下的源码实现,完整梳理 dm-zoned 的架构设计、写缓冲算法、磁盘元数据布局、元数据保护机制、reclaim 回收过程与 dmzadm/dmsetup 实际使用方法。读完本文,你将理解 host-managed 与 host-aware 两种分区块设备模型下 dm-zoned 的工作原理,并掌握从格式化、加载 target 到监控状态与手动触发回收的完整实操链路。

一、dm-zoned 解决的问题与设计目标

1.1 背景:分区块设备的写约束

分区块设备(zoned block device)将存储空间划分为固定大小的 zone。其中 sequential zone(顺序写 zone)要求写入必须严格从 zone 写指针(write pointer)位置顺序推进,任何乱序写、覆盖写都会被设备拒绝;只有 conventional zone(常规 zone,即随机写 zone) 允许任意地址随机写入。文档中将其划分为 ZBC(SCSI 设备)与 ZAC(ATA 设备)两个规范家族。

这一约束让上层文件系统与裸设备应用难以直接使用这类硬盘。dm-zoned 正是在此背景下提出的内核级解决方案。

1.2 dm-zoned 的目标形态

dm-zoned.rst 明确指出:dm-zoned 将一块 ZBC/ZAC 分区块设备暴露为无任何写模式约束的常规块设备,等效于实现了一块“drive-managed zoned block device(设备托管型分区块设备)”。其价值在于:

  • host-managed(主机托管型) 设备:向用户(文件系统或裸设备应用)隐藏顺序写约束;
  • host-aware(主机感知型) 设备:缓解设备端因过多随机写导致的潜在性能劣化。

官方文档对实现的总体评价是“simple and minimizes system overhead”——即在 CPU 开销、内存占用与存储容量损失三个方面都做到最小化。文档给出的量化参考:对于一块 10TB、256MB zone 的 host-managed 硬盘,每个磁盘实例的 dm-zoned 内存占用最多不超过 4.5MB,且内部仅需约 5 个 zone 用于存放元数据与执行回收(reclaim)操作。该开销极小的特性与下文 4KB 逻辑块、压缩化元数据布局的设计直接相关。

二、核心架构:两类 zone、两级设备与 4KB 逻辑块

2.1 zone 的功能划分

dm-zoned 把设备上(或多个设备)的全部 zone 分成两类(见 dm-zoned.rst):

  1. 元数据 zone(Metadata zones):属于 conventional zone,用于保存 dm-zoned 自身管理所需元数据。这部分 zone 不会作为可用容量上报给用户
  2. 数据 zone(Data zones):其余全部 zone。其中绝大部分是专门存放用户数据的 sequential zone;设备的 conventional zone 也可用于缓冲用户随机写——即写入的数据可以先把常规 zone 当作随机写缓冲,之后再搬移到 sequential zone,把常规 zone 腾出来继续承接新的随机写流量。

在源码 drivers/md/dm-zoned.h 中,zone 的用途通过位标志刻画:DMZ_META(元数据)、DMZ_DATA(数据)、DMZ_BUF(缓冲区)、DMZ_RESERVED(保留),再叠加写类型 DMZ_RND(随机 zone)、DMZ_SEQ(顺序 zone),以及较新版本引入的 DMZ_CACHE(缓存 zone),供 dmz_is_meta / dmz_is_data / dmz_is_buf / dmz_is_seq / dmz_is_rnd 等访问器使用(dm-zoned.h)。

2.2 常规块设备 + 分区块设备的双设备组合

dm-zoned 不仅支持单块分区块设备,还支持将一个常规块设备与分区块设备组合使用(文档见 dm-zoned.rst)。其做法是:

  • 常规块设备被按分区块设备的 zone 大小做逻辑切分,切分出的“逻辑 zone”放在分区块设备的所有 zone 之前
  • 这些逻辑 zone 被当作 conventional zone 使用(充当缓存/随机写缓冲),实际数据最终仍沉淀到真正的分区块设备上。

这一点在较新源码中体现为每个 struct dmz_dev 持有 zone_offset(该设备 zone 号的起始偏移)与 dev_idx(设备序号),并通过设备标志 DMZ_BDEV_REGULAR 标识常规块设备(dm-zoned.h)。多设备场景下第一个设备通常只承担 cache(常规随机写缓冲)zone 的角色。

2.3 固定的 4KB 逻辑块与扇区

dm-zoned 暴露的逻辑设备扇区大小固定为 4096 字节,与底层分区块设备的物理扇区大小无关。文档给出的理由是:更大的逻辑块粒度可以显著压缩用于管理“有效块(已写且未被丢弃的块)”的元数据量

源码通过一组宏将其固化(drivers/md/dm-zoned.h):

/* dm-zoned creates block devices with 4KB blocks, always. */
#define DMZ_BLOCK_SHIFT         12
#define DMZ_BLOCK_SIZE          (1 << DMZ_BLOCK_SHIFT)
#define DMZ_BLOCK_MASK          (DMZ_BLOCK_SIZE - 1)

#define DMZ_BLOCK_SECTORS_SHIFT (DMZ_BLOCK_SHIFT - SECTOR_SHIFT)
#define DMZ_BLOCK_SECTORS       (DMZ_BLOCK_SIZE >> SECTOR_SHIFT)
#define DMZ_BLOCK_SECTORS_MASK  (DMZ_BLOCK_SECTORS - 1)

/* 4KB block <-> 512B sector conversion. */
#define dmz_blk2sect(b)         ((sector_t)(b) << DMZ_BLOCK_SECTORS_SHIFT)
#define dmz_sect2blk(s)         ((sector_t)(s) >> DMZ_BLOCK_SECTORS_SHIFT)

即内部所有记账都以 4KB 块为单位,块号与 512B 扇区之间通过移位换算,bio 在进入目标时由 dmz_bio_block() / dmz_bio_blocks() 归一化为块号。

2.4 逻辑地址到 zone 的按 chunk 映射

dm-zoned 的逻辑设备地址空间被切分为chunk,chunk 大小等于底层 zone 大小。每个 chunk 对应一条映射记录,指示存放该 chunk 数据的 zone。源码 drivers/md/dm-zoned.h 中的两个宏清晰地表达了这一点:

#define dmz_bio_chunk(zmd, bio) ((bio)->bi_iter.bi_sector >> \
                                 dmz_zone_nr_sectors_shift(zmd))
#define dmz_chunk_block(zmd, b) ((b) & (dmz_zone_nr_blocks(zmd) - 1))

bio 起始扇区右移 zone_nr_sectors_shift 位即得到 chunk 号;dmz_chunk_block 则把块号投影到 chunk 内部(等价于 mod zone 块数)。这种设计保证了一个 chunk 恰好对应一个 zone 的容量,简化了映射与回收时的地址换算。

三、写缓冲算法与读写路径

3.1 对常规 zone 的直接写

若某个逻辑 chunk 被映射到 conventional zone,则所有写操作都直接写入该 zone,无需任何缓冲。随机写性能与普通块设备一致。

3.2 对顺序 zone 的对齐写与缓冲写

若 chunk 映射到 sequential zone,写操作是否直接下发取决于写偏移是否对齐 zone 写指针

  • 对齐写:chunk 内的写偏移 == 顺序 zone 内写指针偏移时,写操作直接下发到该 zone;
  • 未对齐写:此时写操作改走 buffer zone(缓冲 zone) 间接完成。dm-zoned 会分配一个空闲 conventional zone 作为该 chunk 的缓冲 zone,把未对齐的随机写落到缓冲 zone 中。

在源码层面,zone 描述符 struct dm_zone 通过 bzone 指针把主映射 zone 与其缓冲 zone 互相关联:对顺序数据 zone,它指向用来处理未对齐写的随机 zone;对缓冲 zone,它指回数据 zone(drivers/md/dm-zoned.h)。而按 chunk 映射与缓冲分配的核心函数为 dmz_get_chunk_mapping()dmz_get_chunk_buffer()(声明于 dm-zoned.h)。

写入缓冲 zone 一个块时,会自动使顺序 zone 中对应位置的同一块失效——这正是通过按块维护的 bitmap 实现的关键机制(见下文第四节)。当顺序 zone 的所有块都被写失效后,该 zone 即被释放,缓冲 zone 顺势“转正”成为该 chunk 的主映射 zone,此时该 chunk 后续写入重新表现为原生随机写,性能与普通块设备相当。

3.3 读路径与“补零读”

读操作按 bitmap 提供的块有效性信息执行:

  • chunk 映射的 zone(或缓冲 zone)中有效块:直接从对应位置读取;
  • 未映射 chunk 或所访问块已失效:dm-zoned 不会发起底层读,而是将读缓冲区清零后立即结束该读请求(即返回全零数据),避免无意义地访问已失效数据。

对文件系统而言,这种“读到已丢弃块返回零”的语义与普通写后校验的块设备行为一致,保证了逻辑一致性。源码 drivers/md/dm-zoned-metadata.c 中通过 dmz_block_valid()dmz_validate_blocks()dmz_invalidate_blocks() 实现块级有效性查询与翻转,在 target 侧 dmz_map() 中据以决定实际下发路径。

四、磁盘元数据格式

文档给出的 on-disk 元数据布局如下(细节可对照 drivers/md/dm-zoned-metadata.cstruct dmz_superstruct dmz_map 与宏 DMZ_MAP_ENTRIES 的实现):

  1. Super block(超级块,1 个 4KB 块):位于找到的第一个 conventional zone 的第一块,描述元数据块在盘上的数量与位置。源码中的 on-disk 结构 struct dmz_superdm-zoned-metadata.c)只使用 512B、但占据整块 4KB,字段包括:

    • magic:魔数 DZBD('D')<<24 | ('Z')<<16 | ('B')<<8 | ('D')),用于识别 dm-zoned 元数据;
    • version:元数据版本号,当前实现为 DMZ_META_VER 2
    • gen64 位世代计数器(generation counter),用于主/备元数据集新旧判定;
    • nr_meta_blocks:元数据块总数(含超级块自身);
    • nr_reserved_seq:为回收(reclaim)预留的顺序 zone 数量;
    • nr_chunks:映射表条目数;
    • nr_map_blocks:chunk 映射表占用的块数;
    • nr_bitmap_blocks:有效性 bitmap 占用的块数;
    • crc:校验和;
    • dmz_label[32]dmz_uuid[16]dev_uuid[16]:标签、dm-zoned 实例 UUID 与底层设备 UUID。

    整体 on-disk 布局在注释中概括为:(1) Super block (1 block) → (2) Chunk mapping table (nr_map_blocks) → (3) Bitmap blocks (nr_bitmap_blocks),全部存放在从盘上第一个 conventional zone 起的元数据 zone 中。

  2. Chunk 映射表(Chunk mapping table):紧随超级块的若干块,用于描述逻辑设备块的映射。映射按 chunk 进行(chunk 大小即底层 zone 大小),映射表以 chunk 号为索引,每个条目给出存储该 chunk 数据的 zone 号,并且可能额外指出一个用于缓冲该 chunk 随机修改的 conventional zone 号。源码 struct dmz_mapdm-zoned-metadata.c)恰好两个 32 位字段:dzone_idbzone_id;每个 4KB 块可容纳 DMZ_MAP_ENTRIES = 512 个 8 字节条目(dm-zoned-metadata.c),DMZ_MAP_UNMAPPED = UINT_MAX 表示未映射。这一点在源码注释中有清晰的佐证:“if it is a sequential zone, a second zone (bzone_id) used as a write buffer may also be specified. This second zone will always be a randomly writeable zone.”

  3. 块有效性 bitmap(Bitmaps):映射表之后是一组块,存放各数据 zone 内块的有效性位图。有效块定义为“已写入且未被丢弃”的块。对于被缓冲的数据 chunk,其某个块只可能在两种位置之一有效:要么在映射该 chunk 的数据 zone 中,要么在该 chunk 的缓冲 zone 中(绝不同时有效),从而保证了读路径二选一的正确性。

五、元数据保护与 flush 提交点

5.1 双元数据集 + 世代计数

为应对突然断电或系统崩溃导致的元数据损坏,dm-zoned 使用两份元数据 zone 集

  • 主集(primary set):作为主元数据区常驻使用;
  • 备集(secondary set):作为暂存区(staging area)。

其更新流程遵循“先备后主、世代确认”的提交协议(详见 dm-zoned.rst):

  1. 被修改的元数据先写入备集
  2. 通过更新备集中的超级块并利用世代计数器(generation counter) 指示备集包含最新元数据,从而“验证”备集;
  3. 验证完成后,才在主元数据集内就地更新元数据块。

该机制保证任意时刻两份集合中总有一份是完整一致的(要么所有修改全部提交,要么一个都没有提交),崩溃后总能从有效的那一份恢复。

5.2 flush 作为提交点

Flush 请求被用作元数据提交点。当收到 flush 请求时:

  • 元数据修改活动被暂时阻塞(既阻塞新的 BIO 处理,也阻塞 reclaim 回收进程);
  • 所有脏元数据块被 staged(暂存)并完成更新;
  • 随后恢复正常操作。

因此一次元数据 flush 只会短暂延迟写与 discard(丢弃)请求;文档特别强调,元数据 flush 执行期间读请求可以并发处理。这与 flush 串行化、读无需加元数据锁的设计取向一致,也解释了为什么 dm-zoned 能把系统开销控制得很低。

5.3 双设备场景的第三份标识元数据

当常规块设备与分区块设备配合使用时(见 dm-zoned.rst):

  • 1、2 份元数据(含 bitmap 的完整元数据)位于常规块设备开头的元数据 zone 内;
  • 另有一份不含 zone bitmap 的第三份元数据写入分区块设备开头,其世代计数固定为 0,正常运行期间永远不会被更新,仅用于设备识别(identification)目的。

5.4 锁与 flush 的源码印证

源码将元数据同步与并发控制在 drivers/md/dm-zoned.h 暴露为清晰的锁接口:dmz_lock_map / dmz_lock_metadata / dmz_lock_flush 及对应的 unlock 版本,加上 dmz_flush_metadata() 执行实际落盘。target 侧 drivers/md/dm-zoned-target.c 维护独立的 flush 工作队列与 DMZ_FLUSH_PERIOD (10 * HZ) 周期定时器,将积压的 flush/写请求批量提交,从而摊薄元数据写入的固定开销。

六、Reclaim:常规 zone 的回收与重排

6.1 为什么需要 reclaim

conventional zone 的数量是有限的。持续运行一段时间后,空闲常规 zone 可能全部被占用(要么被映射到 chunk,要么正充当顺序 zone 的缓冲 zone),此时对未缓冲 chunk 的未对齐写将无法继续。为避免死锁式停滞,dm-zoned 内置 reclaim(回收)后台进程

6.2 reclaim 的目标与复制策略

文档描述的回收逻辑是:reclaim 进程定期扫描已使用的常规 zone,把“最久未使用(least recently used)”的 zone 中缓冲的有效块复制到空闲 sequential zone;复制完成后更新 chunk 映射指向该顺序 zone,并释放原缓冲 zone 供复用

从源码看,回收按被回收 zone 的三种状态执行不同的策略(见 drivers/md/dm-zoned-reclaim.cdmz_do_reclaim() 分发逻辑):

  • dmz_reclaim_buf():回收“被用作缓冲的 zone”——把缓冲 zone(bzone)中的有效块复制回其主数据 zone(dzone),随后释放缓冲 zone;
  • dmz_reclaim_rnd_data():回收“映射 chunk 的常规数据 zone”——先分配空闲顺序 zone,把该常规 zone 的有效块复制过去,更新映射后释放常规 zone;
  • dmz_reclaim_seq_data():回收“纯顺序数据 zone”——把 dzone 中有效块合并(merge)进其缓冲 zone,再释放 dzone;
  • dmz_reclaim_empty():被回收 zone 已无有效块时直接释放,免去复制。

所有数据搬迁都经由内核的 dm-kcopyd 客户端异步完成(drivers/md/dm-zoned-reclaim.c),单 zone 复制期间通过 DMZ_RECLAIM_KCOPY 位串行化,避免同一 zone 上的复制互相重叠。

6.3 回收触发阈值与限速(当前源码与文档的差异)

官方文档对触发条件的表述是:“一旦空闲常规 zone 少于 50% 就开始回收”。不过需要说明的是,当前仓库中 dm-zoned target 版本为 {2,0,0},其实际阈值逻辑已演进(drivers/md/dm-zoned-reclaim.c):

/* Percentage of unmapped (free) random zones below which reclaim starts */
#define DMZ_RECLAIM_LOW_UNMAP_ZONES      30
/* Percentage of unmapped (free) random zones above which reclaim will stop */
#define DMZ_RECLAIM_HIGH_UNMAP_ZONES     50

结合 dmz_should_reclaim()dm-zoned-reclaim.c)可得到当前实现下的真实触发规则:

  • 空闲(无活跃 IO)且存在可回收 zone 时,总是执行回收
  • 空闲常规 zone 百分比 ≥ 50%(HIGH) 时,即使空闲也不回收(“还不缺”);即文档所述“低于 50% 才启动”这一上限语义仍在,只是现在由 HIGH 水位表达;
  • 空闲常规 zone 百分比 ≤ 30%(LOW) 时,即便 target 繁忙也会强制回收,以免随机写完全无法进行;
  • 双设备场景下,若第一块设备仅含 cache zone,则永不在该设备上启动回收(dm-zoned-reclaim.c)。

回收速度也做了自适应限速:通过 dmz_reclaim_percentage() 计算空闲比例后,dmz_reclaim_work() 设置 kcopyd 节流值——target 空闲或空闲比例极低(低于 LOW 的一半)时以 100 全速回收;繁忙但仍有富余常规 zone 时,节流值取 min(75, 100 - p_unmap / 2),在保证回收进度的同时尽量不拖累用户业务 IO(dm-zoned-reclaim.c)。

6.4 保留顺序 zone

Super block 中有一个值得注意的字段 nr_reserved_seqdrivers/md/dm-zoned-metadata.c):它记录为 reclaim 预留的顺序 zone 数量。这是回收过程可持续性的关键前提——只有始终留有空闲顺序 zone 作为复制目标,回收流水线才能持续运转,用户容量 = 全部 zone − 元数据 zone − 保留顺序 zone。

七、实际操作:格式化、加载、状态查询与手动回收

7.1 使用 dmzadm 格式化分区块设备

分区块设备必须先由 dmzadm 工具格式化。该工具(由 dm-zoned 作者维护的独立用户态工具集)会分析设备的 zone 配置,决定两份元数据集在盘上的安放位置,并完成元数据初始化。

单设备格式化:

dmzadm --format /dev/sdxx

若使用“常规块设备 + 分区块设备”双盘组合,则两个设备都必须指定,且常规块设备必须作为第一个设备(对应前文 2.2 节“逻辑 zone 排在最前”的布局约定):

dmzadm --format /dev/sdxx /dev/sdyy

7.2 用 dmzadm 启动已格式化设备

格式化完成的设备也可以用 dmzadm 启动(其内部会调用 dmsetup 装载内核 dm-zoned target):

dmzadm --start /dev/sdxx /dev/sdyy

7.3 查询内部布局与 zone 用量:dmsetup status

关于设备内部布局与 zone 当前使用情况,可通过 dmsetup 的 status 回调查询:

dmsetup status /dev/dm-X

官方文档给出的经典单设备输出为一行:

0 <size> zoned <nr_zones> zones <nr_unmap_rnd>/<nr_rnd> random <nr_unmap_seq>/<nr_seq> sequential

各字段含义:

  • <nr_zones>:zone 总数;
  • <nr_unmap_rnd>:空闲(未映射)随机 zone 数;
  • <nr_rnd>:随机 zone 总数;
  • <nr_unmap_seq>:空闲顺序 zone 数;
  • <nr_seq>:顺序 zone 总数。

需要提醒的是:当前仓库源码中 dm-zoned target 版本为 {2,0,0}(见 drivers/md/dm-zoned-target.cstruct target_type zoned_target),dmz_status()STATUSTYPE_INFO 分支实际输出的格式已经扩展为带 cache zone 统计的形式(dm-zoned-target.c):

<总zone数> zones <空闲cache>/<总cache> cache <空闲随机>/<总随机> random <空闲顺序>/<总顺序> sequential

其中双设备场景下,若第一台设备只含 cache zone,则其 random/sequential 统计会被跳过、仅输出 cache 计数。两者分别刻画的是不同内核版本的行为:文档保留的是早期单设备格式;以本仓库源码为准的读者请按 2.0.0 版本的实际输出(含 cache 字段)解析。

7.4 手动触发回收:dmsetup message

正常情况下,回收在空闲比例跌破阈值后自动开始。若希望在到达阈值之前手动启动回收,可使用 dmsetup 的 message 函数

dmsetup message /dev/dm-X 0 reclaim

该命令会触发 reclaim 进程,把随机(常规)zone 中的数据搬移到顺序 zone、释放常规 zone。源码中对应 dmz_message() 的回调:当消息为 reclaim 时,对 target 下的每一块底层设备逐一调用 dmz_schedule_reclaim() 以立即调度回收工作项(drivers/md/dm-zoned-target.c);若消息不被识别则返回错误并记录 unrecognized message

八、源码组织与内核配置

8.1 三文件模块划分

dm-zoned 的源码高度模块化,全部位于 drivers/md/,由三部分组成(drivers/md/Makefile):

dm-zoned-y += dm-zoned-target.o dm-zoned-metadata.o dm-zoned-reclaim.o
obj-$(CONFIG_DM_ZONED) += dm-zoned.o

三者通过头文件 drivers/md/dm-zoned.h 统一接口契约。构建与装载由内核配置项 CONFIG_DM_ZONED 控制。

8.2 目标能力与错误处理

在 target 描述符中可以看到 dm-zoned 具备 DM_TARGET_SINGLETON | DM_TARGET_MIXED_ZONED_MODEL 特性(drivers/md/dm-zoned-target.c#L1143):前者保证一个映射设备上只能有一个该 target,后者表示它可以同时处理分区块设备与常规块设备混合的底层拓扑——与 2.2 节双设备设计相互印证。

zone 级错误处理同样在源码中可见:当对顺序 zone 的写失败时,target 会在 zone 上置 DMZ_SEQ_WRITE_ERR 标志并把设备标记为 DMZ_CHECK_BDEVdrivers/md/dm-zoned-target.c);设备“将死(dying)”时,dmz_dev_is_dying() 会引导回收与写路径及时退出,避免在坏设备上无限重试。

8.3 与通用块层的衔接

dm-zoned 并不重新发明 zone 发现逻辑,而是依赖通用 dm 层提供的 zone 报告基础设施:本仓库 drivers/md/dm-zone.c 中的 dm_blk_report_zones() / dm_report_zones_cb() 负责把底层各 target(含 dm-zoned)的 zone 信息汇聚上报给块层。dm-zoned 只负责在 zone 之上实现映射、缓冲与回收,从而与 blk-mq、zone 重新校验(zone revalidate)等机制平滑衔接。

九、关键设计取舍与适用建议

综合文档与源码,可以提炼出 dm-zoned 的几条关键设计取舍,供实际选型与排障时参考:

  1. 容量换随机写能力,但损失被压到极小:文档给出 10TB/256MB zone 场景下仅约 5 个 zone 被内部占用(元数据 + 回收),内存开销 ≤ 4.5MB/盘。用户可见容量损失近乎可忽略。
  2. 4KB 固定块粒度:元数据按块记账,配合 4KB 逻辑扇区,bitmap 与映射表体积可控;缺点是小于 4KB 的 IO 需要由上层对齐/合并。
  3. 缓冲“转正”路径:某个 chunk 的顺序 zone 被写满无效数据后直接释放、缓冲 zone 转为主映射 zone,是 dm-zoned 能把常规 zone 流量长期维持在高吞吐的关键——它会动态把随机写热点 chunk 变成真正的随机写 zone
  4. 回收是吞吐的守卫:当空闲常规 zone 逼近 30% 水位或设备空闲时回收才加速;繁忙且富余时会主动限速。若出现大量未对齐随机写且常规 zone 不足,优先通过 dmsetup message ... reclaim 手动回收,或评估底层盘上常规 zone 配额是否足够。
  5. 双元数据集保证崩溃一致性:读请求在 flush 期间仍可并行处理,是 dm-zoned 保持低延迟的重要细节;不要在高并发只读负载下误判其为写路径瓶颈。

若需深入探索,建议从 drivers/md/dm-zoned-metadata.c 的 super block 读写与 drivers/md/dm-zoned-reclaim.c 的 zone 调度开始阅读;用户态配套工具 dmzadm 需在 dm-zoned-tools 独立仓库获取,与内核侧版本应保持匹配(本仓库元数据版本为 DMZ_META_VER 2,格式化的盘如需回读须使用兼容版本工具)。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388