fix lack of rename - #445
Conversation
|
build_prs |
|
Job is started, see https://github.com/vivoblueos/kernel/actions/runs/31395200189. |
|
Job is started, see https://github.com/vivoblueos/kernel/actions/runs/31396448273. |
|
✅ All jobs completed successfully, see https://github.com/vivoblueos/kernel/actions/runs/31395200189. |
|
✅ All jobs completed successfully, see https://github.com/vivoblueos/kernel/actions/runs/31396448273. |
| struct FatFile { | ||
| _parent: Weak<FatInode>, | ||
| internal_file: InternalFsLock<File>, | ||
| internal_file: InternalFsLock<Option<File>>, |
There was a problem hiding this comment.
rust-fatfs::Dir::rename requires that no live File instance references the entry being renamed; otherwise the old File may later update the original directory entry and corrupt the filesystem.
BlueOS keeps a fatfs::File persistently inside FatInode, so Option<File> allows the rename path to take() and drop that handle before calling Dir::rename, then reopen the file under its new name and store it back afterward. If rename fails, the original file is reopened.
The None state exists only during the rename critical section while the inode write lock is held. Other file operations return EIO if this invariant is unexpectedly violated.
Using mem::replace would still require a dummy live File, so it would not satisfy the library’s rename requirement.
You can see it in https://github.com/rafalh/rust-fatfs/blob/c4b88477b22ca7e5131fbd8891f62a5deaa88e6e/src/dir.rs#L388
| let (new_dir, new_name) = match path::find_parent_and_name(new_path) { | ||
| Some(result) => result, | ||
| None => return -libc::ENOENT, | ||
| }; |
There was a problem hiding this comment.
If there is a file with new_path, how to handle this case
| } | ||
|
|
||
| let mut source_inner = self.inner.write(); | ||
| let mut target_inner = target.inner.write(); |
There was a problem hiding this comment.
A deadlock may occur here (AB-BA).
| child_inner.as_dir_mut().ok_or(code::EIO)?.parent = target.this.clone(); | ||
| source_inner.dec_nlinks(); | ||
| target_inner.inc_nlinks(); | ||
| } |
There was a problem hiding this comment.
check whether to move the dir to its subdir.
Description
This commit completes
renamesupport in the BlueOS kernel VFS. It adds the syscall entry, resolves source and destination paths through VFS, updates dcache state, and implements rename for both FATFS and tmpfs.The external
rust-fatfslibrary already providesDir::rename, so no external-library modification is required.Call path
std::fs::renamereaches the filesystem through the normal BlueOS syscall and VFS path:Syscall number (
header/src/lib.rs):Renameis appended beforeLastNR, preserving all existing syscall numbers.Syscall handler (
kernel/src/syscall_handlers/mod.rs): registers therename(old_path, new_path)handler and dispatch-table entry. Builds without VFS returnENOTSUP.Path resolution (
kernel/src/vfs/syscalls.rs): validates both pointers and UTF-8 paths, resolves both parent directories withfind_parent_and_name, then callsold_dir.rename(old_name, &new_dir, new_name). Errors are returned as normal errno values.Dcache update (
kernel/src/vfs/dcache.rs): validates the source entry and mount-point state, rejects an existing destination, calls the filesystem inode implementation, moves the cached child, and updates its stored name and parent. Renaming a path to itself succeeds only after confirming that the source exists.FATFS implementation (
kernel/src/vfs/fatfs.rs):FatInode::renamevalidates both directories and filesystem ownership, callsrust-fatfs::Dir::rename, and synchronizes the internalFatDir.childrenmaps. Cross-directory directory moves also update the moved directory’s parent reference.tmpfs implementation (
kernel/src/vfs/tmpfs.rs): supports same-directory rename and cross-directory moves. Cross-directory moves update child maps, directory size counters, parent link counts, and the moved directory’s..parent reference.FAT file-handle safety
rust-fatfsrequires that no livefatfs::Filereference exists while its directory entry is renamed.FatFile::internal_fileis therefore stored asOption<File>. During rename:Dir::renameupdates the FAT directory entry.If rename fails, the original path is reopened. If reopening the destination fails, the code attempts to roll the directory entry back to its original name before returning the error.
Normal read, write, resize, and fsync paths return
EIOif the internal handle is unexpectedly absent.Error handling
The implementation returns errors instead of panicking:
EINVAL:"."or".."names, invalid pointers or pathsENOENT: missing source or parent directoryEEXIST: destination already existsENOTDIR: source or destination parent is not a directoryEXDEV: source and destination belong to different filesystemsEBUSY: source is a mount pointEIO: inconsistent internal FAT inode stateThe newly added FATFS and tmpfs rename paths contain no
unwrap()calls.Tests
kernel/src/vfs/syscalls.rsadds coverage for:QEMU functional test:
Verification
qemu_riscv64.releasekernel and shell rename path compiled successfully.git diff --checkpassed.check_allwas not run.FBIOGET_FSCREENINFO,FBIOGET_VSCREENINFO, andFBIOPUT_VSCREENINFOconstants.