Linux 内核 dm-zoned 完全指南:在 Device Mapper 层将分区块设备包装为普通块设备
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):
- 元数据 zone(Metadata zones):属于 conventional zone,用于保存 dm-zoned 自身管理所需元数据。这部分 zone 不会作为可用容量上报给用户。
- 数据 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.c 中 struct dmz_super、struct dmz_map 与宏 DMZ_MAP_ENTRIES 的实现):
-
Super block(超级块,1 个 4KB 块):位于找到的第一个 conventional zone 的第一块,描述元数据块在盘上的数量与位置。源码中的 on-disk 结构
struct dmz_super(dm-zoned-metadata.c)只使用 512B、但占据整块 4KB,字段包括:magic:魔数DZBD(('D')<<24 | ('Z')<<16 | ('B')<<8 | ('D')),用于识别 dm-zoned 元数据;version:元数据版本号,当前实现为DMZ_META_VER 2;gen:64 位世代计数器(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 中。 -
Chunk 映射表(Chunk mapping table):紧随超级块的若干块,用于描述逻辑设备块的映射。映射按 chunk 进行(chunk 大小即底层 zone 大小),映射表以 chunk 号为索引,每个条目给出存储该 chunk 数据的 zone 号,并且可能额外指出一个用于缓冲该 chunk 随机修改的 conventional zone 号。源码
struct dmz_map(dm-zoned-metadata.c)恰好两个 32 位字段:dzone_id与bzone_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.” -
块有效性 bitmap(Bitmaps):映射表之后是一组块,存放各数据 zone 内块的有效性位图。有效块定义为“已写入且未被丢弃”的块。对于被缓冲的数据 chunk,其某个块只可能在两种位置之一有效:要么在映射该 chunk 的数据 zone 中,要么在该 chunk 的缓冲 zone 中(绝不同时有效),从而保证了读路径二选一的正确性。
五、元数据保护与 flush 提交点
5.1 双元数据集 + 世代计数
为应对突然断电或系统崩溃导致的元数据损坏,dm-zoned 使用两份元数据 zone 集:
- 主集(primary set):作为主元数据区常驻使用;
- 备集(secondary set):作为暂存区(staging area)。
其更新流程遵循“先备后主、世代确认”的提交协议(详见 dm-zoned.rst):
- 被修改的元数据先写入备集;
- 通过更新备集中的超级块并利用世代计数器(generation counter) 指示备集包含最新元数据,从而“验证”备集;
- 验证完成后,才在主元数据集内就地更新元数据块。
该机制保证任意时刻两份集合中总有一份是完整一致的(要么所有修改全部提交,要么一个都没有提交),崩溃后总能从有效的那一份恢复。
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.c 的 dmz_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_seq(drivers/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.c 的 struct 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
- dm-zoned-target.c:target 生命周期与 BIO 处理主路径。实现
zonedtarget(单例 target),map回调按 chunk 分发 BIO、按需克隆下发,并负责 flush 工作队列与消息处理(drivers/md/dm-zoned-target.c#L1140-L1155); - dm-zoned-metadata.c:on-disk 元数据读写、super block 校验、chunk 映射表与 bitmap 维护、元数据双集 flush;
- dm-zoned-reclaim.c:回收工作队列、zone 选择与 kcopyd 数据搬迁。
三者通过头文件 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_BDEV(drivers/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 的几条关键设计取舍,供实际选型与排障时参考:
- 容量换随机写能力,但损失被压到极小:文档给出 10TB/256MB zone 场景下仅约 5 个 zone 被内部占用(元数据 + 回收),内存开销 ≤ 4.5MB/盘。用户可见容量损失近乎可忽略。
- 4KB 固定块粒度:元数据按块记账,配合 4KB 逻辑扇区,bitmap 与映射表体积可控;缺点是小于 4KB 的 IO 需要由上层对齐/合并。
- 缓冲“转正”路径:某个 chunk 的顺序 zone 被写满无效数据后直接释放、缓冲 zone 转为主映射 zone,是 dm-zoned 能把常规 zone 流量长期维持在高吞吐的关键——它会动态把随机写热点 chunk 变成真正的随机写 zone。
- 回收是吞吐的守卫:当空闲常规 zone 逼近 30% 水位或设备空闲时回收才加速;繁忙且富余时会主动限速。若出现大量未对齐随机写且常规 zone 不足,优先通过
dmsetup message ... reclaim手动回收,或评估底层盘上常规 zone 配额是否足够。 - 双元数据集保证崩溃一致性:读请求在 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,格式化的盘如需回读须使用兼容版本工具)。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00