RK3588 kernel-6.1 extents.c 与 extents_status.c 分析

RK3588 kernel-6.1 extents.cextents_status.c 分析

1. 分析范围

文件 行规模(约) 角色
fs/ext4/extents.c 6000+ 盘上 extent B+ 树的查找、插入、分裂/合并、截断拆洞、map_blocks、未写入区段转换、FIEMAP / iomap
fs/ext4/extents_status.c 2300+ 内存中的 extent 状态树(ES tree):延迟块、洞、已写/未写区间的按逻辑块序 RB 树,与 delalloc / bigalloc / fiemap / SEEK_DATA|HOLE 协作;shrinker 回收;pending reservation 子树

配套头文件与概念:ext4_extents.hext4_extentext4_extent_idxext4_ext_path 等)、ext4.hstruct extent_status / ext4_es_tree


2. 两者关系(一句话)

extents.c 维护 inode 内持久化的 extent 索引树(决定块在磁盘上的归属与未写标记);extents_status.c 维护同一 inode 上不写入磁盘的 逻辑区间状态缓存,使延迟分配、大簇、映射查询和空洞语义不必反复扫 page cache 或全盘 extent 树。**


3. extents_status.c:作用与解决的问题

3.1 代码作用(一句话)

为每个 extent 类 inode 建一棵按逻辑起始块 es_lblk 排序的红黑树,节点表示一段连续逻辑块及其 状态(delayed / written / unwritten / hole 等)与可选物理映射;提供 插入、删除、查找、区间扫描、与预留簇计数,并在内存压力下通过 shrinker 丢弃除 delayed 外可丢弃节点。

3.2 解决的问题

问题 做法
FIEMAP、SEEK_DATA/SEEK_HOLE 靠翻 page cache 识别延迟区 在 ES 树中可直接判断某逻辑范围是否为 delayed 或洞
bigalloc 下是否要对簇做 quota 预留 ext4_es_scan_clu / ext4_clu_mapped 等可查簇是否已有 delayed 或已映射,避免重复预留
写回路径为判断 delayed 扫整棵 page cache 查 ES 树 O(log n) + cache_es 热路径近似 O(1)
延迟分配与真实分配、截断、状态不同步 ext4_es_insert_extent / ext4_es_remove_extent / ext4_es_insert_delayed_blockext4_map_blocksinode.c 等成对维护
碎片 extent 导致 ES 树过大 ext4_es_register_shrinker:在压力下回收 written/unwritten/hole 类节点,不回收 delayed(注释:fiemap、bigalloc、seek 仍需要)
bigalloc + delalloc 的「待定簇预留」 另一棵 ext4_pending_tree(pending reservation),ext4_is_pending__insert_pending / __revise_pendingext4_es_insert_delayed_block(..., allocated) 协作,避免簇级预留重复或遗漏
从盘上读出的区间写入 ES(可选缓存) ext4_es_cache_extent:若该范围尚无记录则插入,避免覆盖更新的内存状态

3.3 核心 API(概念)

  • ext4_es_init_tree / ext4_clear_inode_es:挂载/释放 inode 时树生命周期。
  • ext4_es_insert_extent覆盖式更新(先 __es_remove_extent__es_insert_extent),可合并相邻同类 extent;FC_REPLAY 时直接返回。
  • ext4_es_lookup_extent:供 ext4_map_blocks / ext4_da_map_blocks 先查内存;维护 命中/未命中 统计。
  • ext4_es_remove_extent:截断、转换、失效时撕掉区间;bigalloc 下配合 init_rsvd / count_rsvd 调整 reserved cluster 计数。
  • ext4_es_insert_delayed_block:单逻辑块标 DELAYED;若 allocated 则挂 pending。
  • ext4_es_delayed_cluext4_ext_map_blocks 等在非 delalloc 分配路径上扣减「仅 delayed」簇的预留。
  • 并发EXT4_I(inode)->i_es_lock(读写锁)。

3.4 设计注释中的「Step1/Step2」

当前内核已完成「全状态可进树 + shrinker」方向;原文仍保留历史名称 delay extent tree 与向 extent 级加锁 等未来工作的叙述,阅读时以现实现为准。


4. extents.c:作用与解决的问题

4.1 代码作用(一句话)

实现 ext4 的 extent 特性下的盘上多级索引 B+ 树(根可在 inode 内或外部块):查找逻辑块对应的叶 ext4_extent插入/分裂/提升树高合并相邻 extent删除与截断ext4_ext_remove_space)、未写入 extent 与初始化 extent 的分裂与转换,并向 ext4_map_blocks 提供 ext4_ext_map_blocks;同时负责 extent 块校验和损坏校验ext4_ext_check_*)及 FIEMAP / collapse_range / insert_range 等高层次接口。

4.2 解决的问题

问题 做法
大文件用直接/间接块表浪费与低效 用 extent 描述 (逻辑起始, 物理起始, 长度),树高随范围数对数增长
写时分配、块边界与邻居 extent 对齐 ext4_ext_find_goalext4_ext_search_left/rightext4_mb_new_blocks 传入簇对齐后的 goal/logical
bigalloc 下逻辑块与簇 get_implied_cluster_allocEXT4_LBLK_COFF/CMASK 等,在 ext4_ext_map_blocks 中复用已隐含簇
未写入(unwritten)extent 与落盘 查找命中 unwritten 时 ext4_ext_handle_unwritten_extents / ext4_ext_convert_to_initialized 等分裂、转换;direct I/O 结束 ext4_convert_unwritten_io_end_vec
truncate / punch hole / collapse / insert range ext4_ext_remove_space 从叶向上删块、收缩索引;ext4_ext_truncate 更新 i_disksize 并与 remove 路径配合;文件操作层 collapse/insert
事务额度与 i_data_sem 死锁 ext4_datasem_ensure_credits + ext4_ext_trunc_restart_fn:必要时放下 i_data_sem、丢弃预分配、重启事务
元数据块损坏 ext4_extent_block_csum_*ext4_valid_extent*ext4_ext_check_inode
fast commit 重放等特殊路径 ext4_ext_replay_update_exext4_ext_clear_bb 等(与日志重放一致)

4.3 典型调用链(映射)

  1. ext4_ext_map_blocksext4_find_extent 定位路径 → 若在叶 ext4_extent 内则返回 mapped 或走 unwritten 分支 → 若需创建且带 EXT4_GET_BLOCKS_CREATEext4_mb_new_blocksext4_ext_insert_extent
  2. 插入失败时 释放刚分配的簇ext4_discard_preallocations
  3. delalloc 成功路径可 ext4_da_update_reserve_spaceext4_es_delayed_clu 与 ES 树侧预留对齐。

4.4 与 extents_status.c 的衔接(代码层面)

  • ext4_map_blocks(在 inode.c)通常会先 ext4_es_lookup_extent;盘上树路径在 ext4_ext_map_blocks 内仍通过 ext4_find_extent 访问。
  • 分配/转换/截断成功后,extent 代码路径会调用 ext4_es_insert_extentext4_es_remove_extent(具体分散在 extents.cinode.cfast_commit.c 等),保持 ES ↔ 盘树 一致。

4.5 extents.c 内部重要符号(导航)

类别 代表符号
路径与查找 ext4_find_extent(本文件前部)、ext4_ext_search_left/right
修改树形 ext4_ext_insert_extentext4_ext_splitext4_ext_grow_indepthext4_ext_try_to_merge_*
删除 ext4_ext_remove_spaceext4_remove_blocksext4_ext_rm_leaf
映射入口 ext4_ext_map_blocks
用户可见 ext4_fiemapext4_get_es_cache
校验 ext4_ext_check_inodeext4_valid_extent

5. 小结表

维度 extents_status.c extents.c
数据落盘 否(纯内存) 是(inode 或 extent 块)
主要结构 struct extent_status RB 树 + pending 树 ext4_extent_header + index + leaf
核心价值 延迟/洞/映射的快速查询与 bigalloc 预留逻辑 持久块映射与树形维护
典型读者 delalloc、fiemap、seek、shrink 分配器、截断、未写转换、fsck 相关检查

两篇合起来构成 ext4 “内存 extent 视图 + 盘上 extent 索引” 的完整拼图;分析 ext4_map_blocksext4_da_map_blocks 时应同时打开 inode.c 与上述两文件。

文章互动

阅读 --

留言

0 条留言

正在加载留言…