RK3588 kernel-6.1 fs/ext4/mballoc.c 多块分配器(mballoc)分析

RK3588 kernel-6.1 fs/ext4/mballoc.c 多块分配器(mballoc)分析

1. 分析范围

  • rk3588/kernel-6.1/fs/ext4/mballoc.c(约 6700+ 行,ext4 数据块/簇 的主分配与释放实现)
  • 头文件与结构:mballoc.hext4_allocation_request / ext4_allocation_contextext4_group_info 中的 buddy/prealloc 字段
  • 调用方:extents.c / indirect.cext4_mb_new_blocks)、inode.c(延迟分配、ext4_claim_free_clusters 等)、ioctl.cFITRIMext4_trim_fs)、fsmap.cext4_mballoc_query_range

2. 代码作用(一句话)

mballoc.c块组粒度 上维护 位图 + buddy 树(通过 s_buddy_cache 伪 inode 的页缓存 装载),按 goal、stripe、CR(cr 0/1) 与可选 mb_optimize_scan 选择块组;分配路径 优先吃 inode 预分配 / per-CPU 局部性预分配,否则 规范化请求长度 后在 buddy 上 查找、分裂、标记已用,并写回 块位图、gdt 空闲计数、簇计数bigalloc 下以 为 accounting 单位);释放路径 ext4_free_blocks 清位图、buddy、quota,并支持 日记 forget/revoke;另提供 TRIM(discard)对空闲区间的枚举回调(getfsmap)。


3. 解决了什么问题

问题 处理方式
传统按块扫描位图,大块分配慢且碎片严重 buddy:按 2 的幂阶 合并/分裂空闲区,快速找到 足够长的连续空闲簇
每分配一次就写位图,小文件随机写放大 预分配(PA)inode 级 i_prealloc_list(按 逻辑块 覆盖)、per-CPU s_locality_groups(按 剩余空闲 消费);未用完的规范化余量 挂回 PA 列表
小文件也希望物理相邻 小请求(低于 s_mb_stream_request,可 sysfs 调)倾向 组级预分配,使小文件 同组聚集
大块/顺序写希望一次拿长连续区 ext4_mb_normalize_request:按 文件大小启发mb_group_preallocstripe放大申请长度,多拿的进 PA
多 CPU 争用同一 free list locality group 按 CPU 分桶;buddy 页在组锁 ext4_lock_group 下更新
buddy 与位图占用内存 s_buddy_cache:按需 ext4_mb_load_buddy,位图+buddy 两 block/组 映射到 页缓存;卸载丢弃
选组从 O(N) 扫描 可选 mb_optimize_scans_mb_largest_free_orders(最大空闲阶链表)、s_mb_avg_fragment_size(按 bb_free/bb_fragments 分桶),注释称 CR0/CR1 阶段近似 O(1) 选组
RAID stripe 对齐 s_stripeext4_mb_scan_aligned 等,尝试 与条带对齐的连续分配
配额与全局空闲簇 ext4_claim_free_clusters / dquot_alloc_blockext4_mb_new_blocks 开头);失败时 缩短 len 重试-EDQUOT/-ENOSPC
延迟分配已预留簇 EXT4_MB_DELALLOC_RESERVED跳过 claim/quot 中的 “必须有可用块” 分支,与 s_dirtyclusters_counter 配合
fast commit 重放 ext4_mb_new_blocks_simple / ext4_free_blocks_simple:简化路径
释放时集群边界 ext4_free_blocksEXT4_PBLK_COFF / EXT4_LBLK_COFF 处理 首尾部分簇EXT4_FREE_BLOCKS_NOFREE_* 控制是否动边界簇
释放块合法性 ext4_inode_block_valid(除非 VALIDATED);防 释放数据区外块
FITRIM / SSD discard ext4_trim_fs:按 fstrim_range 遍历块组,ext4_trim_all_free够长的空闲簇 sb_issue_discard(受 granularity、minlen 约束)
getfsmap 需要枚举组内空闲 ext4_mballoc_query_range:在 [start,end] 簇 内对 0 bit 段formatterfsmap.c 使用)
在线加组后 buddy 初始化 ext4_mb_init_groupext4_mb_add_groupinfo 等与 resize 协作

4. 主路径概要

4.1 分配:ext4_mb_new_blocks

  1. TRACE / FC_REPLAY → simple。
  2. 非 delalloc reservedext4_claim_free_clusters + dquot_alloc_block(配额文件可用 nofail)。
  3. ext4_mb_initialize_context:填充 ext4_allocation_context(含 goal、flags)。
  4. ext4_mb_use_preallocated:命中 inode PA 则直接 ext4_mb_mark_diskspace_used
  5. 否则 ext4_mb_normalize_requestext4_mb_pa_alloc(创建/填充上下文中的 PA)→ ext4_mb_regular_allocatorext4_mb_find_by_goal / simple / complex / scan_aligned` 等)。
  6. ext4_mb_mark_diskspace_used:日记 get_access、位图置位、buddy 更新、gdt、ext4_es_insert_extent 由调用方负责。
  7. 失败:ext4_mb_pa_free / ext4_discard_allocated_blocks、释放配额预留。

4.2 释放:ext4_free_blocks

可选 ext4_forget(元数据或 data journal 语义)→ ext4_mb_clear_bb(清位图、更新 buddy、gdt、percpu_counter 等)。


5. 调试与 sysfs(文件头注释摘录)

可调参数包括 mb_stream_reqmb_group_preallocmb_min_to_scanmb_max_to_scanmb_order2_reqmb_linear_limit 等与 stripemb_optimize_scan 挂载选项;/sys/fs/ext4/<dev>/ 下暴露。


6. 小结

mballoc.c 是 ext4 数据区空间管理 的核心:在块组内用 buddy 做连续空闲管理,在文件系统级用 PA 做吞吐与局部性;与 bigalloc(簇)quota、journal、FC 重放、discard、fsmap 深度绑定。阅读 ext4_map_blocksext4_mb_new_blocks 时,应以 ext4_allocation_request 各字段(goal/logical/len/flags 为线索;阅读 碎片与延迟分配 时结合 extents_status.cinode.c delalloc

深层算法细节(mb_mark_used 分裂 buddy、ext4_mb_good_group_nolock、prefetch 等)可在本文件内按符号继续下钻,本文不展开到函数级伪代码。

文章互动

阅读 --

留言

0 条留言

正在加载留言…