RK3588 kernel-6.1 fs/ext4/ialloc.c inode 分配与回收分析

RK3588 kernel-6.1 fs/ext4/ialloc.c inode 分配与回收分析

1. 分析范围

  • rk3588/kernel-6.1/fs/ext4/ialloc.cinode 位图读写校验、新建 inode释放 inodeOrlov/目录投递策略orphan 校验统计与 lazyinit inode 表清零
  • 协作:namei.c / inode.c(调用 __ext4_new_inode)、ext4_jbd2(位图与组描述符日记)、xattr.c/acl.c/fscrypt(新 inode 初始化)、mballoc/flex(组内空闲簇统计与 s_flex_groups

2. 代码作用(一句话)

ialloc.c 用每个块组一张 inode 位图 + 组描述符中的空闲 inode/目录计数 管理 inode 号的分配与回收;新建时按 目录 Orlov、普通文件近父组+二次探测block group,在位图中 find_next_zero_bit事务内置位,顺带处理 BG_INODE_UNINIT/BG_BLOCK_UNINITflex_bg 计数与 配额/ACL/extent 树 初始化;释放时先 ext4_clear_inode 再清位图,避免 inode 号快速复用导致别名


3. 解决了什么问题

问题 处理方式
目录集中导致单块组 inode 或目录密度过大 find_group_orlov:顶级/标记 TOPDIR 的目录可按 目录名 hash 或随机 分散到 flex_bg;一般子目录在 空闲 inode/簇不低于均值、目录数不过阈 的组中挑选,失败再 fallback 到「空闲 inode ≥ 组均值」的线性搜索
同一目录下普通文件尽量同组、又避免与邻目录过度混放 find_group_other:优先 父组(flex 内扫描);不行则用 (parent_group + i_ino) % ngroups 为种子做 二次增量探测 + 最后线性扫
块组 inode 位图未初始化(INODE_UNINIT ext4_read_inode_bitmap:在 gdt csum 下可将位图 内存填 0 并 ext4_mark_bitmap_end 标记已用尾部,避免读盘;新建 inode 时可能触发 block bitmap 首次初始化BLOCK_UNINIT
inode 位图损坏或未授权重放 ext4_validate_inode_bitmapCRC 校验EXT4_SIM_*EXT4_MB_GRP_IBITMAP_CORRUPT拒绝使用
释放 inode 后立即复用同一编号与旧 dentry/缓存打架 ext4_free_inode:注释强调须先 ext4_clear_inode清位图无 journalfind_inode_bit + recently_deleted 尽量避免 刚删未落盘的 inode 槽
组内最后一位被并发抢走 __ext4_new_inodeext4_test_and_set_bit 失败持锁重搜 或换 next_group 循环
goal/保留 inode 范围 goal 可强制 起始组与位偏移EXT4_FIRST_INO 以下视为保留,若被清出则 报错并标位图损坏
orphan 链表恢复 ext4_orphan_get位图须仍置位 表示 inode 仍被占用;检查 ext4_can_truncate/NEXT_ORPHAN 等,防止 坏 orphan 死循环
lazyinit 未完成时 inode 表含垃圾 ext4_init_inode_tablealloc_sem 写锁 阻塞同组 ext4_new_inode,对 INODE_ZEROED 的表 sb_issue_zeroout 并置 BG_INODE_ZEROED
ext4 与内核/调试统计 ext4_count_free_inodes / ext4_count_dirs;DEBUG 下可 逐组对账位图与 gdp 计数

4. 核心流程

4.1 inode 位图读入:ext4_read_inode_bitmap

  • gdpinode bitmap 块号,范围自检。
  • INODE_UNINIT零填充 + 尾部 mark used,标 uptodate/verified,不读盘。
  • 否则 读盘ext4_validate_inode_bitmapext4_inode_bitmap_csum_verify)。

4.2 新建:__ext4_new_inode

  1. new_inode、owner/ fscrypt_prepare_new_inodedquot_initialize,按需累加 xattr 事务额度
  2. 选组goal → 否则目录 find_group_orlov,文件 find_group_other;更新 dir->i_last_alloc_group
  3. 每个候选组:gdp 空闲计数为 0ibitmap corrupt 则跳过;读 inode bitmapfind_inode_bit 找 0 bit。
  4. journal get_write_access 位图 → 置位(冲突则重找)→ dirty 位图
  5. BLOCK_UNINIT:读并 dirty block bitmap,清 EXT4_BG_BLOCK_UNINIT,初始化 free_clusters
  6. 更新 gdpfree_inodes--、目录则 used_dirs++,维护 bg_itable_unused / INODE_UNINITinode bitmap / gdp csum
  7. 维护 percpu_counterflex free_inodes/used_dirs
  8. 填写 ext4_inode_infoi_block_groupi_csum_seedEXTENT 标志 + ext4_ext_tree_init(目录/ reg / symlink)、i_sync_tid 等,insert_inode_lockedACL/security/encrypt xattrext4_mark_inode_dirty

4.3 释放:ext4_free_inode

前置条件检查i_count/i_nlink)→ dquot_free_inodeext4_clear_inode → 算 group/bit → 读位图、journal 访问清 bit(若已清则 报错 corrupt)→ 更新 gdp 空闲 inode、目录计数、flex、percpu重算 inode bitmap csum / gdp csumdirty

4.4 辅助出口

  • ext4_mark_inode_used:重放或工具路径 强制在位图中置位 并更新计数(与 __ext4_new_inode 不同,不创建 VFS inode)。
  • ext4_orphan_get:挂载 orphan 处理。
  • ext4_init_inode_tablelazyinit 后台 inode 表零填充

5. 小结

ialloc.c 是 ext4 inode 编号空间 的核心:位图一致性(校验和 + corrupt 标记)目录/文件的局部性与负载均衡(Orlov + flex)与 lazyinit、日记、配额、extent 初始化 的衔接都在此收敛。分析 creat/mkdir/unlink 时,分配侧看 __ext4_new_inodefind_group_*,回收侧看 ext4_free_inodeext4_evict_inode(在 inode.c)的调用关系。

文章互动

阅读 --

留言

0 条留言

正在加载留言…