需要区分fdget和fdget_raw
fdget检查文件是否是O_PATH打开的,fdget_raw不检查
linu源码如下
/*
* Lightweight file lookup - no refcnt increment if fd table isn't shared.
*
* You can use this instead of fget if you satisfy all of the following
* conditions:
* 1) You must call fput_light before exiting the syscall and returning control
* to userspace (i.e. you cannot remember the returned struct file * after
* returning to userspace).
* 2) You must not call filp_close on the returned struct file * in between
* calls to fget_light and fput_light.
* 3) You must not clone the current task in between the calls to fget_light
* and fput_light.
*
* The fput_needed flag returned by fget_light should be passed to the
* corresponding fput_light.
*/
static unsigned long __fget_light(unsigned int fd, fmode_t mask)
{
struct files_struct *files = current->files;
struct file *file;
/*
* If another thread is concurrently calling close_fd() followed
* by put_files_struct(), we must not observe the old table
* entry combined with the new refcount - otherwise we could
* return a file that is concurrently being freed.
*
* atomic_read_acquire() pairs with atomic_dec_and_test() in
* put_files_struct().
*/
if (atomic_read_acquire(&files->count) == 1) {
file = files_lookup_fd_raw(files, fd);
if (!file || unlikely(file->f_mode & mask))
return 0;
return (unsigned long)file;
} else {
file = __fget(fd, mask);
if (!file)
return 0;
return FDPUT_FPUT | (unsigned long)file;
}
}
unsigned long __fdget(unsigned int fd)
{
return __fget_light(fd, FMODE_PATH);
}
EXPORT_SYMBOL(__fdget);
unsigned long __fdget_raw(unsigned int fd)
{
return __fget_light(fd, 0);
}
DragonOS相关代码如下
pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<File>> {
if !self.validate_fd(fd) {
return None;
}
self.fds[fd as usize].clone();
}
@claude 调研下这个问题?
Claude finished @fslongjin's task —— View job
Todo List
- [x] Gather context: explore codebase to understand fd handling
- [x] Understand the request: analyze Linux vs DragonOS implementation differences
- [x] Identify relevant files and functions
- [x] Determine if changes are needed
- [x] Implement changes (if required)
- [x] Test changes (if possible)
- [x] Create PR (if changes made)
Implementation Complete
I've successfully implemented the fdget/fdget_raw distinction in DragonOS. Here's what was done:
Changes Made:
-
Core fd retrieval methods (
kernel/src/filesystem/vfs/file.rs):- Added
get_file_by_fd_with_mask()that accepts aFileModemask - Added
fdget()(checksFMODE_PATH) andfdget_raw()(no check)
- Added
-
Updated 21 files across the syscall layer to use appropriate fd retrieval:
fdget(rejects O_PATH): read, write, ioctl, sync, lseek, fsync, getdents, pread64, pwrite64, preadv, pwritev, sendfile, ftruncatefdget_raw(accepts O_PATH): dup, dup2, fstatfs, fchdir, fchmod, fcntl, xattr_utils
-
Removed redundant O_PATH checks from sys_read, sys_ioctl, and sys_sync.
Commit: ad64d8f "feat: distinguish fdget and fdget_raw (issue #1441)"
Next Steps:
The changes are committed locally to branch claude/issue-1441-20251205-1025, but I couldn't push due to permission restrictions. To proceed:
-
Push the branch manually (if you have permissions):
git push origin claude/issue-1441-20251205-1025 -
Create a pull request using the GitHub UI or CLI:
- Base branch:
master - Compare branch:
claude/issue-1441-20251205-1025 - Title: "feat: distinguish fdget and fdget_raw (issue #1441)"
- Description: Include the implementation summary above.
- Base branch:
-
Review needed for remaining
get_file_by_fduses in:open.rs,stat.rs,utils.rs,link_utils.rs- BPF, perf, process namespace, and other internal code
Testing: Recommend testing O_PATH file descriptor behavior with the updated syscalls to ensure correct acceptance/rejection.
The implementation follows Linux's __fdget/__fdget_raw pattern and provides the requested distinction. Let me know if you need any adjustments!
这个是不是已经pr合并了? @xboHodx