RK3588 kernel-6.1 fs/ext4/balloc.c 块位图与块组元数据辅助分析

RK3588 kernel-6.1 fs/ext4/balloc.c 块位图与块组元数据辅助分析

1. 分析范围

  • rk3588/kernel-6.1/fs/ext4/balloc.c
  • mballoc.cext4_mb_new_blocks)、ext4.h 中块组宏、super.c 挂载初始化、ialloc.c 等资源统计的协作关系

2. 代码作用(一句话)

balloc.c 负责 ext4「块组 / 物理块号」相关的算术、块位图(block bitmap)的读入与校验/惰性初始化、每组元数据开销与「空闲簇」簿记(含预留与重试),并为元数据分配提供入口;现代 ext4 上「大块连续分配」本体在 mballoc.cballoc.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_counters_dirtyclusters_counters_resv_clustersr_blocks_count 等判断;低于 watermark 时做一次 percpu_counter 精确求和root 保留块CAP_SYS_RESOURCEEXT4_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_supersparse_supersparse_super2、组 0/1 等规则决定本组是否有超级块备份。
  • ext4_bg_num_gdbmeta_bg 与传统布局下,本组内 组描述符表 占块数。

ext4_num_base_meta_blocks 一起支撑 resizefsck 语义理解位图初始化 时「哪些 bit 必须为 1」。

3.8 分配起点 hint:ext4_inode_to_goal_block

  • 使用 inode 所在块组 i_block_groupflex_bg 足够大时,目录等普通文件 分到 flex 内不同组以改善局部性与 fsck。
  • 未开 DELALLOC 时用 pid 上色colour)在同组内打散,减轻锁竞争;开 DELALLOC 时直接 组起始块 作 goal。

解决的问题:在 mballoc 决策前给出局部性友好的物理 hint,而非完全盲目搜索。

3.9 调试与一致性统计

  • ext4_count_free_clustersEXT4FS_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_descext4_get_group_info

因此:**「balloc」**一名更反映历史;当前应理解为 block bitmap & block group 基础设施,而不是「所有块都在此分配」。


5. 数据流示意(简化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
挂载 / 首次访问某组
|
v
ext4_read_block_bitmap* → ext4_validate_block_bitmap
|
+--> UNINIT: ext4_init_block_bitmap(内存生成)
|
v
mballoc 分配
|
v
ext4_has_free_clusters / ext4_claim_free_clusters
|
v
ENOSPC → ext4_should_retry_alloc(journal commit)

6. RK3588 / 工程注意点

  • 存储:eMMC/UFS 上 ext4 很常见;位图校验失败会 按组标记损坏,表现为 该组分区的分配失败或只读,需结合 dmesgfsck
  • 延迟分配 + ENOSPCext4_should_retry_allocjournal 相关,无 journal(极少见配置)时重试逻辑不同。
  • bigalloc:所有 「簇」 级计数与 EXT4_B2C 等宏与 balloc.c 一致,排查「统计不准」时要核对 s_cluster_bits

7. 关键导出符号/函数速查

1
2
3
4
5
6
7
8
9
10
11
ext4_get_group_number / ext4_get_group_no_and_offset
ext4_get_group_desc / ext4_get_group_info
ext4_read_block_bitmap / ext4_read_block_bitmap_nowait / ext4_wait_block_bitmap
ext4_free_clusters_after_init
ext4_has_free_clusters(static,对外经 ext4_claim_free_clusters)
ext4_claim_free_clusters
ext4_should_retry_alloc
ext4_new_meta_blocks
ext4_count_free_clusters
ext4_bg_has_super / ext4_bg_num_gdb / ext4_num_base_meta_blocks
ext4_inode_to_goal_block

8. 小结

维度 结论
作用 块组算术、块位图生命周期与校验、元数据开销与空闲簇簿记、元数据块分配入口、super/GDT 布局辅助、分配 goal
解决问题 在给定磁盘布局下 安全、惰性、可校验 地维护「哪一簇空闲」,并与 mballoc、journal、预留块 协同,避免错误分配与错误 ENOSPC

源码路径:rk3588/kernel-6.1/fs/ext4/balloc.c。文档路径:linuxDoc/fs/ext4/

文章互动

阅读 --

留言

0 条留言

正在加载留言…