RK3588 kernel-6.1 fs/ext4/balloc.c 块位图与块组元数据辅助分析
1. 分析范围
rk3588/kernel-6.1/fs/ext4/balloc.c- 与
mballoc.c(ext4_mb_new_blocks)、ext4.h中块组宏、super.c挂载初始化、ialloc.c等资源统计的协作关系
2. 代码作用(一句话)
balloc.c 负责 ext4「块组 / 物理块号」相关的算术、块位图(block bitmap)的读入与校验/惰性初始化、每组元数据开销与「空闲簇」簿记(含预留与重试),并为元数据分配提供入口;现代 ext4 上「大块连续分配」本体在 mballoc.c,balloc.c 是其底层与位图、组描述符之间的粘合层与策略辅助。
文件开头注释也写明:
1 | * balloc.c contains the blocks allocation and deallocation routines |
历史沿革上继承自 ext2/ext3;ext4 引入 mballoc 后,数据块 多由 mballoc 完成,但 位图管理、组布局、空闲计数与 ext4_new_meta_blocks 仍集中在本文件及相关调用链中。
3. 解决了什么问题
3.1 块号 ↔ 块组 + 位图偏移
ext4 按 块组 管理位图;给定全局 物理块号(或 cluster),必须可靠换算:
ext4_get_group_number:根据STD_GROUP_SIZE等挂载选项走快速路径或调用ext4_get_group_no_and_offset。ext4_get_group_no_and_offset:减去s_first_data_block后对EXT4_BLOCKS_PER_GROUP取模,再按s_cluster_bits右移得到 簇级 位图下标(与 bigalloc 一致)。
解决的问题:统一块/簇与位图索引,避免分配与校验时用错组或错 bit。
3.2 哪些块根本不能用于数据分配(元数据开销)
ext4_num_base_meta_blocks/ext4_num_base_meta_clusters:超级块备份、GDT/备份、meta_bg 布局下每组 GDT 占用等。ext4_num_overhead_clusters:在基础元数据之上,再把 块位图、inode 位图、inode table 所占簇计入(含非连续布局的特殊情况)。ext4_free_clusters_after_init:对 未初始化位图 组,在位图不可用时不靠数bits,而用「组内簇数 − 开销」得到空闲簇数。
解决的问题:正确区分可分配数据区与位图/表项,用于挂载、统计与 lazy bitmap init 的初始内容生成。
3.3 块位图:读盘、校验、惰性初始化
ext4_init_block_bitmap:若组描述符 校验和失败,标记位图损坏并相当于 整组只读防分配;否则memset后对 基础元数据簇 及 块/inode 位图、inode 表 对应 bit 置 1(已用),并对组尾 padding 置 1(ext4_mark_bitmap_end)。ext4_read_block_bitmap_nowait/ext4_wait_block_bitmap/ext4_read_block_bitmap:拿buffer_head、必要时提交读;若EXT4_BG_BLOCK_UNINIT且支持 checksumming,则在锁内 在内存中生成位图 并标 uptodate(无需先读盘)。ext4_validate_block_bitmap:CRC(ext4_block_bitmap_csum_verify)、自洽性(块/inode 位图块号、inode 表区间在位图中须为已占用)、尾部 padding 必须为 1;FLEX_BG 下部分检查跳过(位图可能不在本组)。
解决的问题:检测损坏/篡改、支持 未初始化块组 减少 mkfs 后首次挂载 IO,并保证位图与组描述符描述一致。
3.4 组描述符与 per-group 运行时信息
ext4_get_group_desc:用block_group索引到 GDT 所在块 + 组内偏移,返回struct ext4_group_desc *(挂载与 mballoc 大量使用)。ext4_get_group_info:返回ext4_group_info(mballoc 的 buddy 等 per-group 结构指针)。
解决的问题:从逻辑组号定位磁盘元数据,并把 balloc 与 mballoc 接到同一套组结构上。
3.5 全文件系统「是否还有空闲簇」与 ENOSPC 重试
ext4_has_free_clusters:用s_freeclusters_counter、s_dirtyclusters_counter、s_resv_clusters与r_blocks_count等判断;低于 watermark 时做一次 percpu_counter 精确求和;root 保留块、CAP_SYS_RESOURCE、EXT4_MB_USE_ROOT_BLOCKS/EXT4_MB_USE_RESERVED有特殊规则。ext4_claim_free_clusters:在认为有空间时把需求量加到dirtyclusters_counter(与延迟分配、未落盘「已预订」语义配合)。ext4_should_retry_alloc:分配返回 ENOSPC 时,若有 journal,可jbd2_journal_force_commit_nested等,等待事务落盘释放位图,最多重试 3 次;与 DISCARD work 等也有交互。
解决的问题:避免过早 ENOSPC(脏元数据尚未提交)、与 quota/预留块 策略一致,并给上层 ext4_set_acl、xattr、inode 分配 等 -ENOSPC 重试 提供统一判据(见其他文件对 ext4_should_retry_alloc 的调用)。
3.6 元数据块分配入口
ext4_new_meta_blocks:填充ext4_allocation_request后调用ext4_mb_new_blocks,用于 索引块、extent 树块等元数据;支持EXT4_MB_DELALLOC_RESERVED时的 quota 记账。
解决的问题:元数据分配与数据分配共用 mballoc,但 API 与标志集中在一处,便于与 handle 事务 对齐。
3.7 超级块 / GDT 备份布局
ext4_bg_has_super:sparse_super、sparse_super2、组 0/1 等规则决定本组是否有超级块备份。ext4_bg_num_gdb:meta_bg 与传统布局下,本组内 组描述符表 占块数。
与 ext4_num_base_meta_blocks 一起支撑 resize、fsck 语义理解 与 位图初始化 时「哪些 bit 必须为 1」。
3.8 分配起点 hint:ext4_inode_to_goal_block
- 使用 inode 所在块组
i_block_group;flex_bg 足够大时,目录等 与 普通文件 分到 flex 内不同组以改善局部性与 fsck。 - 未开 DELALLOC 时用 pid 上色(
colour)在同组内打散,减轻锁竞争;开 DELALLOC 时直接 组起始块 作 goal。
解决的问题:在 mballoc 决策前给出局部性友好的物理 hint,而非完全盲目搜索。
3.9 调试与一致性统计
ext4_count_free_clusters:EXT4FS_DEBUG下可对照组描述符累加值与位图逐位统计;非 DEBUG 则只累加组描述符中的空闲量(跳过已知损坏位图组)。
4. 与 mballoc.c 的分工(理解重点)
| 层面 | balloc.c |
mballoc.c |
|---|---|---|
| 位图缓冲区 | 读/校验/init | 分配路径中大量使用已验证位图 |
| 实际找位、预分配、buddy | 不承担 | ext4_mb_new_blocks 等 |
| 元数据分配 API | ext4_new_meta_blocks → mballoc |
执行分配 |
| 组号/开销/GDT | 核心 | 消费 ext4_get_group_desc、ext4_get_group_info |
因此:**「balloc」**一名更反映历史;当前应理解为 block bitmap & block group 基础设施,而不是「所有块都在此分配」。
5. 数据流示意(简化)
1 | 挂载 / 首次访问某组 |
6. RK3588 / 工程注意点
- 存储:eMMC/UFS 上 ext4 很常见;位图校验失败会 按组标记损坏,表现为 该组分区的分配失败或只读,需结合
dmesg与fsck。 - 延迟分配 + ENOSPC:
ext4_should_retry_alloc与 journal 相关,无 journal(极少见配置)时重试逻辑不同。 - bigalloc:所有 「簇」 级计数与
EXT4_B2C等宏与balloc.c一致,排查「统计不准」时要核对s_cluster_bits。
7. 关键导出符号/函数速查
1 | ext4_get_group_number / ext4_get_group_no_and_offset |
8. 小结
| 维度 | 结论 |
|---|---|
| 作用 | 块组算术、块位图生命周期与校验、元数据开销与空闲簇簿记、元数据块分配入口、super/GDT 布局辅助、分配 goal |
| 解决问题 | 在给定磁盘布局下 安全、惰性、可校验 地维护「哪一簇空闲」,并与 mballoc、journal、预留块 协同,避免错误分配与错误 ENOSPC |
源码路径:rk3588/kernel-6.1/fs/ext4/balloc.c。文档路径:linuxDoc/fs/ext4/。
正在加载留言…