RK3588 kernel-6.1 ext4 目录项(文件名)与 inode 绑定及增删改查

RK3588 kernel-6.1 ext4 目录项(文件名)与 inode 绑定及增删改查

1. 核心结论

  • 文件名不存放在「子文件」自己的 inode 里,而存放在 父目录的数据(目录块或 inline 目录)中,以 struct ext4_dir_entry_2 记录排列。
  • 名字与文件的绑定在盘上就是:目录项里的 de->inode(32 位 inode 号)+ de->name;不是 C 指针,而是 磁盘上的数值关联
  • VFSdentry 缓存「路径上某一分量 → struct inode」,避免每次访问都扫目录块;权威映射仍以盘上目录项为准

2. 盘上目录项格式(绑定字段)

每条目录项(ext4_dir_entry_2,见 ext4.h)主要包括:

  • inode:小端 inode 号 —— 名字指向哪个 inode
  • name / name_len:文件名(加密目录则为密文名等)
  • rec_len:本条总长度(含对齐,用于链接成变长数组)
  • file_type:类型提示(普通文件/目录/软链…)

写入「名字 + inode 号」的典型实现:namei.c ext4_insert_dentry

1
2
3
4
5
de->file_type = EXT4_FT_UNKNOWN;
de->inode = cpu_to_le32(inode->i_ino);
ext4_set_de_type(inode->i_sb, de, inode->i_mode);
de->name_len = fname_len(fname);
memcpy(de->name, fname_name(fname), fname_len(fname));

3. 查(lookup / 路径解析 / readdir)

3.1 lookupopenstat 等)

  1. VFS 对父目录 inode 调 inode_operations.lookup,ext4 为 ext4_lookupnamei.c)。
  2. ext4_lookup_entry:在目录数据里按名查找 ext4_dir_entry_2(线性块或 htree)。
  3. 读出 de->inodeext4_iget(sb, ino, ...) 装入 struct inode
  4. d_splice_alias(inode, dentry)dentryinode 接到目录树上。
1
2
3
4
5
if (bh) {
__u32 ino = le32_to_cpu(de->inode);
brelse(bh);
// ... ino 合法性校验 ...
inode = ext4_iget(dir->i_sb, ino, EXT4_IGET_NORMAL);

3.2 readdir(列目录)

dir.c ext4_readdir / ext4_dx_readdir 扫描目录项,经 dir_emit名字与 inode 号 等交给用户态;每条记录仍对应盘上 de->inode


4. 增(create / mkdir / link)

  1. ext4_new_inode... 分配 新 inodeinode 表中有对应槽位,得到 i_ino)。
  2. ext4_add_entry:在父目录中找空间或分配新目录块(inline → 块htree、线性路径见 namei.c)。
  3. add_dirent_to_bufext4_insert_dentry:在缓冲区写入 名字de->inode = cpu_to_le32(inode->i_ino),经 journal 落盘。

注意ext4_add_entry 注释说明,若条目 de->inode 暂时为 0,须在同逻辑路径内尽快写入 ino,中间不可随意丢锁长睡,否则槽位可能被占用。


  1. ext4_find_entry 定位目录项。
  2. ext4_delete_entry合并 rec_len清零 inode/名,目录中不再出现该名(盘上解绑「名 → ino」)。
  3. drop_nlinkiput、可能 ext4_orphan_add仅当 i_nlink 等条件满足 才在 evict 中回收 inode 与数据块

删名 ≠ 立刻删 inode:硬链接下同一 inode 可对应多条目录项。


6. 改(rename / 覆盖)

  • ext4_rename2ext4_rename / ext4_cross_renamenamei.c):在新位置 ext4_add_entryext4_setent 更新 目标 inode 号与/或名字,再删旧项;覆盖时处理 被覆盖 inode 的 nlink
  • 本质:仍在修改目录块里的 ext4_dir_entry_2inode 与/或 name

7. 磁盘布局与代码地图

概念 位置
目录项增删改查、lookup/rename namei.c
getdents、目录块校验、htree 读 dir.c
htree 遍历时与 hash 协作 hash.c
小目录 inline 形态 inline.c
inode 表定位与 ext4_iget inode.c

8. 与「块设备 I/O」的关系

目录块与普通数据块一样经 页缓存 / buffer_head / bio 读写到 sb->s_bdev本节只描述名字与 inode 的逻辑关系,块层路径见 rk3588-kernel-6.1-ext4-块设备与IO下发路径分析.md


9. 小结

增删改查的对象是 父目录里的目录项序列与 inode 的绑定就是 de->inodestruct inode 存权限、大小、extent 等;文件名只出现在 父目录 的条目中。多篇文档已覆盖 namei 全貌的,可交叉阅读 rk3588-kernel-6.1-ext4-namei路径解析与目录元数据操作分析.md

文章互动

阅读 --

留言

0 条留言

正在加载留言…