Skip to content

Conversation

@xboHodx
Copy link
Contributor

@xboHodx xboHodx commented Feb 2, 2026

2026/2/5

Summary

  • 实现 ext4 文件系统完整的 POSIX rename 语义,包括原子替换和目录循环检测
  • 新增 RENAME_EXCHANGE 支持,实现原子交换两个目录项
  • VFS 层集成 move_to 接口,包含缓存一致性管理
  • 添加全面的用户态测试程序,覆盖各种边界情况

详细变更

1. ext4 底层 rename 实现 (another_ext4/src/ext4/low_level.rs)

原子替换语义:当目标已存在时,不再返回 EEXIST,而是按 POSIX 标准原子替换:

  • 同一 inode → 无操作返回成功
  • 文件替换文件 → 直接替换目录项,递减被替换文件的 link_count
  • 目录替换目录 → 仅允许空目录,正确处理 .. 的 link_count 变更

循环检测:新增 check_ancestor_cycle() 辅助函数,防止把目录移动到自己的子目录下(返回
EINVAL

新增 rename_exchange():实现 RENAME_EXCHANGE 标志功能,原子交换两个目录项的 inode 引用

2. 目录操作扩展 (another_ext4/src/ext4/dir.rs, ext4_defs/dir.rs)

  • dir_replace_entry(): 原地替换目录项的 inode(原子操作核心)
  • dir_is_empty(): 检查目录是否为空(仅含 ...
  • DirEntry::set_inode(): 修改目录项 inode 号

3. VFS 层集成 (kernel/src/filesystem/ext4/inode.rs)

实现 IndexNode::move_to() trait 方法:

  • 处理 RENAME_NOREPLACERENAME_EXCHANGE 标志
  • 替换时清理目标文件的 page cache(调用 truncate_inode_pages
  • 缓存一致性:update_rename_cache()update_exchange_cache() 正确更新 children 映射和 parent
    引用

4. VFS syscall 层 (rename_utils.rs)

  • 添加标志互斥性检查:EXCHANGENOREPLACE/WHITEOUT 互斥
  • RENAME_EXCHANGE 前置检查:目标必须存在

5. 测试 (user/apps/c_unitest/test_rename.c)

约 1000 行全面测试,覆盖:

  • 基本文件/目录重命名
  • 跨目录移动
  • 原子替换(文件覆盖文件、目录覆盖空目录)
  • 类型不兼容错误(文件 vs 目录)
  • 循环检测
  • RENAME_NOREPLACE / RENAME_EXCHANGE 标志
  • 边界情况(同名重命名、./.. 处理等)

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
@fslongjin
Copy link
Member

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa307d6820

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 518 to 522
// 目标必须是 LockedExt4Inode(同一文件系统)
let target_locked = target
.clone()
.downcast_arc::<LockedExt4Inode>()
.ok_or(SystemError::EXDEV)?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject cross-mount renames before using ext4 fs

The downcast only proves target is a LockedExt4Inode, not that it belongs to the same Ext4FileSystem. If target is from another ext4 mount, the code will pass that inode number into the source filesystem (ext4_fs.fs), which can corrupt or misaddress inodes instead of returning EXDEV. Please compare concret_fs() (or an fs id) between self and target_locked and return EXDEV when they differ.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个在另一个pr里面解决了

Comment on lines 588 to 590
}
}
ext4.unlink(target_inode_num, new_name)?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid deleting destination before a failing rename

When the destination exists you remove it (unlink/rmdir) before calling ext4.rename. The underlying ext4 rename can still fail (e.g., ENOSPC or I/O), so this sequence can lose the original destination entry even though the rename didn’t happen. Linux rename is atomic w.r.t. replacement; the destination should remain unchanged if the rename fails. Consider performing the replacement inside a single ext4 operation or ensure rollback when ext4.rename fails.

Useful? React with 👍 / 👎.

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
Signed-off-by: xboHodx <xbohodx2024@gmail.com>
Signed-off-by: xboHodx <xbohodx2024@gmail.com>
@xboHodx
Copy link
Contributor Author

xboHodx commented Feb 3, 2026

想要真正实现原子性还是得日志系统。

@fslongjin
Copy link
Member

fslongjin commented Feb 4, 2026

ext4的更改需要补充充分的测试用例。那个库可以单独cargo test的。

- 新增rename_exchange方法实现原子交换两个目录项
- 添加辅助函数read_rename_dirs和check_ancestor_cycle
- 在VFS层添加EXCHANGE标志处理和缓存更新逻辑
- 遵循POSIX语义实现目录循环检测和跨目录处理

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
- 新增rename_exchange_test函数测试文件/目录交换功能
- 修改BlockFile实现使用Box包装buffer
- 在Cargo.toml中添加workspace配置

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
Signed-off-by: xboHodx <xbohodx2024@gmail.com>
let _r = file.read_exact(&mut buffer);
Block::new(block_id, buffer)
Block::new(block_id, Box::new(buffer))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里为什么要多一次动态内存分配?性能损失

assert_eq!(names, vec!["user.testtwo"]);
}

fn rename_exchange_test(ext4: &mut Ext4) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

测试写单独文件里面去,这个main太长了。

Comment on lines +6 to +7
[workspace]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

清理

@fslongjin
Copy link
Member

@codex review,尤其是看看正确性、并发安全、有没有TOCTOU问题、有没有性能可优化的地方

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 153058aacc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +541 to +545
// NOREPLACE check (VFS layer responsibility - ext4 lib doesn't know about flags)
if flags.contains(RenameFlags::NOREPLACE) && ext4.lookup(target_inode_num, new_name).is_ok()
{
return Err(SystemError::EEXIST);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid TOCTOU in RENAME_NOREPLACE handling

The NOREPLACE path checks ext4.lookup() and then later calls ext4.rename() without holding a filesystem lock or passing the flag down, so a concurrent creator can race between the check and the rename. In that case renameat2(..., RENAME_NOREPLACE) will incorrectly overwrite an existing target, which violates Linux semantics. This is a true TOCTOU introduced by moving atomic-replace behavior into ext4 and keeping NOREPLACE only as a VFS pre-check; the filesystem needs to enforce NOREPLACE atomically or provide a locked rename-with-flags path.

Useful? React with 👍 / 👎.

Comment on lines 557 to 559
if existing_is_dir {
self.dir_remove_entry(&existing_inode, "..")?;
target_dir

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not delete .. in replaced directory

When replacing an existing empty directory, the implementation removes the .. entry from the replaced directory before dropping its link count. If that directory is still reachable via an open fd or is the process’s cwd, Linux keeps .. valid even after unlink/rmdir; removing it makes .. lookups fail or behave inconsistently. The correct behavior is to adjust link counts and remove the parent’s entry, but leave the directory’s .. entry intact until the inode is fully freed.

Useful? React with 👍 / 👎.

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
- 移除link.rs中冗余的目录".."删除操作
- 重构low_level.rs中的rename逻辑,使其更接近Linux ext4实现
- 优化目录移动时的link count处理流程

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
- 取消注释所有被注释的测试代码段
- 确保所有测试用例都能正常执行

Signed-off-by: xboHodx <xbohodx2024@gmail.com>
Signed-off-by: xboHodx <xbohodx2024@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants