fix: complete io_destroy#1165
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
PR 审核总结
修改内容
本 PR 完善了 io_destroy 系统调用和 AIO 子系统的实现,包含两个逻辑部分:
-
AIO 子系统修复(
aio.rs+task/ops.rs)- 将
AioRequest.resfd类型从Option<Arc<dyn FileLike>>改为Option<Arc<EventFd>>,并通过downcast_arc验证IOCB_FLAG_RESFD必须指向 eventfd(符合 Linux 语义) - 提取
destroy_context()辅助函数,供sys_io_destroy和cleanup_aio_contexts_for_pid共用 - 新增
cleanup_aio_contexts_for_pid(),在进程最后一个线程退出时自动清理所有 AIO 上下文,防止内核资源泄漏 - 修复
sys_io_destroy中对全局上下文表的 remove 操作,正确捕获返回的 Arc
- 将
-
测试覆盖
test-io-destroy:新增子进程退出时不调用 io_destroy 的隐式清理回归测试test-io-submit:新增IOCB_FLAG_RESFD搭配非 eventfd fd 时返回EINVAL的验证
-
MySQL 文档(
README.md+README_CN.md)- 补充宿主机 root/sudo 权限要求说明
实现逻辑分析
- resfd 验证:Linux 内核要求
IOCB_FLAG_RESFD仅接受 eventfd(eventfd_fops)。base 分支的旧实现接受任意FileLike,不符合 Linux 行为。PR 使用downcast_arc::<EventFd>()做类型检查,正确匹配内核语义。 - 进程退出清理:Linux 在
exit_files()中调用io_destroy()清理所有 AIO 上下文。PR 将cleanup_aio_contexts_for_pid()放在do_exit()的exit_thread()返回 true(最后一个线程)之后、close_all_fds()之前,与 Linux 的清理顺序一致。这样 worker 任务在销毁过程中仍可引用已打开的 fd。 - destroy_context 提取:将上下文销毁逻辑(设置 destroying 标志、清空队列、等待 inflight 排空、unmap ring buffer)提取为独立函数,避免重复代码。
- sys_io_destroy 修复:旧代码
AIO_CONTEXTS.write().remove(&context.id)忽略了 remove 返回值。新代码正确捕获移除的 Arc 并传入destroy_context()。
验证结果
cargo fmt --check:通过cargo xtask clippy --package starry-kernel:13 个 feature 组合全部通过(0 warnings)- CI 状态:全部通过(SUCCESS)。成功的非跳过检查包括:
Check formatting、Run sync-lint、Run clippy、Test with std、所有架构的 QEMU 测试(starry/aarch64/riscv64/x86_64/loongarch64、arceos、axvisor)和自托管板卡测试。跳过的检查为run_container互斥对应的run_host任务,属于预期行为。 - 无 crates.io patch 依赖
重复/重叠分析
- 搜索
io_destroy、aio、EventFd、resfd关键词的 open PR:仅本 PR(#1165)命中 - PR #1160(Wayland app)和 PR #1076(self-compile)在搜索中出现但实际不重叠:前者是 Wayland app 支持,后者是自编译功能
- base 分支当前无 AIO 进程退出清理实现,本 PR 是唯一的补充
回归测试评估
child_exit_without_io_destroy():fork 子进程 → io_setup → pipe → io_submit(POLL) → 子进程 _exit(0)。验证隐式 AIO 清理后子进程正常退出(exit status 0)。这是对进程退出清理路径的有效回归测试。test-io-submit新增用例:IOCB_FLAG_RESFD搭配普通文件 fd(非 eventfd)→ 验证 io_submit 返回 EINVAL。覆盖 resfd 类型验证逻辑。
无阻塞问题
所有检查通过,实现符合 Linux 语义,测试覆盖了关键路径,CI 全绿。没有发现阻塞性问题。
Powered by mimo-v2.5-pro
ZR233
approved these changes
Jun 6, 2026
ZR233
left a comment
Member
There was a problem hiding this comment.
审查总结
本 PR 修复了 追踪 issue #1157 中描述的三个问题,实现逻辑正确,测试覆盖充分,所有验证通过。
问题 1:AIO context 进程退出清理
实现逻辑:
- 将
sys_io_destroy中的核心销毁流程抽取为destroy_context()内部函数,逻辑复用干净 - 新增
cleanup_aio_contexts_for_pid(pid):获取写锁 → 按 owner 过滤并从全局表移除 → 释放锁 → 逐个调用destroy_context() do_exit()中exit_thread()返回 true(最后一个线程)时,在close_all_fds()和释放 address space 之前调用清理
正确性分析:
- 清理顺序正确:AIO context 持有进程 address space 的 Arc 引用,必须在释放 address space slot 之前销毁
- 锁设计合理:先在写锁内完成全局表移除,再释放锁后执行
wait_for_inflight_drain等阻塞操作,避免死锁 - 与
sys_io_destroy无竞争:若另一线程已通过sys_io_destroy移除同一 context,cleanup_aio_contexts_for_pid的过滤不会匹配到它;反之亦然 sys_io_destroy改进:从lookup_context+remove改为remove(&context.id).ok_or_else(invalid_context),修复了旧代码在 remove 返回 None 时仍执行 destroy 的潜在双重销毁问题
问题 2:IOCB_FLAG_RESFD 校验
实现逻辑:
resolve_resfd()从get_file_like+ 接受任意FileLike改为get_file_like+downcast_arc::<EventFd>()AioRequest.resfd类型从Option<Arc<dyn FileLike>>收窄为Option<Arc<EventFd>>notify_resfd()参数从&Arc<dyn FileLike>收窄为&EventFd- 非 eventfd fd 返回
EINVAL,符合 Linux 行为
正确性分析:
- 类型系统层面保证 completion 路径只对合法 EventFd 写入 8 字节计数
- 避免普通可写文件被误写入 8 字节数据
- 避免不可写 fd 的通知错误被 completion 路径吞掉
问题 3:MySQL README 文档
文档变更正确描述了 rootfs 准备对 root/passwordless sudo 的权限要求,说明了循环缓存机制。纯文档改动,无行为变更。
测试覆盖
- test-io-destroy 新增
child_exit_without_io_destroy():子进程io_setup→ 提交阻塞IOCB_CMD_POLL→ 不调用io_destroy直接_exit(0);父进程waitpid验证子进程正常退出。内核日志确认清理路径:cleared queue, inflight=1, pending=1→all inflight drained - test-io-submit 新增负向用例:
IOCB_FLAG_RESFD+ 普通文件 fd → 验证io_submit返回EINVAL
两个测试都是针对具体 bug 的回归测试,覆盖了修复路径。
验证结果
| 检查项 | 结果 |
|---|---|
cargo fmt --check |
✅ 通过 |
cargo xtask clippy --package starry-kernel(13 个 feature 检查) |
✅ 全部通过 |
cargo xtask starry test qemu --arch x86_64 -c syscall |
✅ 全部通过(test-io-destroy + test-io-submit 含新增用例) |
| CI (GitHub Actions) | ✅ Starry 四架构全部通过,fmt/clippy/sync-lint 通过 |
重复/重叠分析
搜索了 open PR 和 issues,除本 PR 外无其他修复 AIO 清理或 resfd 校验的 PR,无重复。
结论
实现正确、测试充分、无阻塞问题,批准合并。
aptacc2421
pushed a commit
to aptacc2421/tgoskits
that referenced
this pull request
Jun 14, 2026
* fix: complete io_destroy * chore: revise README.md
luodeb
pushed a commit
that referenced
this pull request
Jun 30, 2026
* fix: complete io_destroy * chore: revise README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
修复说明
本 PR 是对 追踪issue的补充,已修复其中所述的三个问题。
问题 1:AIO context 缺少进程退出清理
已修复。
本次改动把
io_destroy中的核心销毁流程抽成内部复用逻辑,并新增按进程pid清理 AIO context 的接口。进程最后一个线程退出时,会在释放/清理address space slot 之前调用该接口,清理该进程拥有的全部 AIO context。
清理行为复用显式
io_destroy的语义:从全局AIO_CONTEXTS表移除 context,设置
destroying,取消队列中尚未执行的请求,唤醒并等待 worker/inflight请求结束,最后 unmap AIO ring。这样即使用户进程没有显式调用
io_destroy,退出路径也不会遗留全局 AIO context、worker,或继续持有已退出进程的 address
space 引用。
同时补充了一个负向/回归测试:子进程
io_setup后提交一个阻塞型IOCB_CMD_POLL请求,然后不调用io_destroy直接退出;父进程等待子进程正常退出,用来覆盖“进程退出触发 AIO 隐式清理”这条路径。
问题 2:IOCB_FLAG_RESFD 未校验 aio_resfd 必须是 eventfd
已修复。
resolve_resfd不再只通过get_file_like(cb.resfd)接受任意FileLike,而是显式 downcast 为
EventFd。如果IOCB_FLAG_RESFD指向的 fd 不是eventfd,
io_submit阶段直接返回EINVAL,不会把普通文件、pipe 或其他 fd当成 AIO completion 通知目标。
AioRequest中保存的 completion 通知目标也从通用FileLike收窄为EventFd,完成路径只会对合法 eventfd 写入 8 字节计数通知。这样可以避免普通可写文件被误写入 8 字节,也避免不可写 fd 的通知错误被 completion 路径吞掉。
测试中补充了
IOCB_FLAG_RESFD + 普通文件 fd的负向用例,确认该组合在io_submit阶段失败并返回EINVAL。问题 3:MySQL app prebuild.sh 依赖 passwordless sudo
这个问题属于 MySQL app rootfs 准备流程的权限约束,不是 AIO 逻辑问题。
当前
apps/starry/mysql/prebuild.sh需要把 ext4 rootfs 镜像接到 loop device并 mount 到临时目录,然后向镜像内安装 MySQL、解包 Debian 依赖并写入
/root/mysql-env.sh。losetup和mount都需要 root 权限,所以普通宿主机用户没有 root 或 passwordless
sudo时,cargo xtask starry app qemu -t mysql --arch x86_64会在 QEMU 启动前失败。本次已在
apps/starry/mysql/README.md和apps/starry/mysql/README_CN.md靠前位置补充说明:MySQL rootfs 准备必须以
root运行,或者由具备passwordless
sudo的用户运行;也可以在具备 root 权限的容器中执行,因为root 容器可以直接完成 loop mount 流程。
需要注意的是,
tmp/axbuild/rootfs/rootfs-x86_64-mysql.img和target/mysql可以复用已生成的 rootfs 与下载缓存,但当前
prebuild.sh仍会检查、扩容、挂载并刷新镜像内容,因此即使缓存存在,现有流程也仍然需要 root 权限。