Add sys_close_range

This commit is contained in:
Cautreoxit
2025-06-01 18:11:06 +08:00
committed by Tate, Hongliang Tian
parent 492898d1d5
commit 3e32a38316
7 changed files with 89 additions and 4 deletions

View File

@ -342,6 +342,7 @@ provided by Linux on x86-64 architecture.
| 328 | pwritev2 | ✅ |
| 332 | statx | ✅ |
| 435 | clone3 | ✅ |
| 436 | close_range | ✅ |
| 439 | faccessat2 | ✅ |
| 441 | epoll_pwait2 | ✅ |

View File

@ -116,6 +116,11 @@ impl FileTableRefMut<'_> {
pub(super) fn remove(&mut self) {
*self.0 = None;
}
/// Replaces the file table with a new one, returning the old one.
pub fn replace(&mut self, new_table: Option<RwArc<FileTable>>) -> Option<RwArc<FileTable>> {
core::mem::replace(&mut *self.0, new_table)
}
}
/// A trait to provide the `as_thread_local` method for tasks.

View File

@ -13,7 +13,7 @@ use crate::syscall::{
chroot::sys_chroot,
clock_gettime::sys_clock_gettime,
clone::{sys_clone, sys_clone3},
close::sys_close,
close::{sys_close, sys_close_range},
connect::sys_connect,
dup::{sys_dup, sys_dup3},
epoll::{sys_epoll_create1, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_pwait2},
@ -302,6 +302,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_UTIMENSAT = 412 => sys_utimensat(args[..4]);
SYS_SEMTIMEDOP = 420 => sys_semtimedop(args[..4]);
SYS_CLONE3 = 435 => sys_clone3(args[..2], &user_ctx);
SYS_CLOSE_RANGE = 436 => sys_close_range(args[..3]);
SYS_FACCESSAT2 = 439 => sys_faccessat2(args[..4]);
SYS_EPOLL_PWAIT2 = 441 => sys_epoll_pwait2(args[..5]);
}

View File

@ -15,7 +15,7 @@ use crate::syscall::{
chroot::sys_chroot,
clock_gettime::sys_clock_gettime,
clone::{sys_clone, sys_clone3},
close::sys_close,
close::{sys_close, sys_close_range},
connect::sys_connect,
dup::{sys_dup, sys_dup2, sys_dup3},
epoll::{
@ -371,6 +371,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_PWRITEV2 = 328 => sys_pwritev2(args[..5]);
SYS_STATX = 332 => sys_statx(args[..5]);
SYS_CLONE3 = 435 => sys_clone3(args[..2], &user_ctx);
SYS_CLOSE_RANGE = 436 => sys_close_range(args[..3]);
SYS_FACCESSAT2 = 439 => sys_faccessat2(args[..4]);
SYS_EPOLL_PWAIT2 = 441 => sys_epoll_pwait2(args[..5]);
}

View File

@ -1,7 +1,20 @@
// SPDX-License-Identifier: MPL-2.0
use bitflags::bitflags;
use ostd::sync::RwArc;
use super::SyscallReturn;
use crate::{fs::file_table::FileDesc, prelude::*};
use crate::{
fs::file_table::{FdFlags, FileDesc},
prelude::*,
};
bitflags! {
struct CloseRangeFlags: u32 {
const UNSHARE = 1 << 1;
const CLOEXEC = 1 << 2;
}
}
pub fn sys_close(fd: FileDesc, ctx: &Context) -> Result<SyscallReturn> {
debug!("fd = {}", fd);
@ -29,3 +42,59 @@ pub fn sys_close(fd: FileDesc, ctx: &Context) -> Result<SyscallReturn> {
// <https://man7.org/linux/man-pages/man2/close.2.html>.
Ok(SyscallReturn::Return(0))
}
pub fn sys_close_range(
first: u32,
last: u32,
raw_flags: u32,
ctx: &Context,
) -> Result<SyscallReturn> {
debug!("first = {}, last = {}, flags = {}", first, last, raw_flags);
if last < first {
return_errno!(Errno::EINVAL);
}
let flags = CloseRangeFlags::from_bits(raw_flags).ok_or_else(|| Error::new(Errno::EINVAL))?;
let original_table = ctx.thread_local.borrow_file_table().unwrap().clone();
let file_table = if flags.contains(CloseRangeFlags::UNSHARE) {
let new_table = RwArc::new(original_table.get_cloned());
let _ = ctx
.thread_local
.borrow_file_table_mut()
.replace(Some(new_table.clone()));
new_table
} else {
original_table
};
let mut files_to_drop = Vec::new();
{
let mut file_table_locked = file_table.write();
let table_len = file_table_locked.len() as u32;
if first >= table_len {
return Ok(SyscallReturn::Return(0));
}
let actual_last = last.min(table_len - 1);
for fd in first..=actual_last {
let fd = fd as FileDesc;
if flags.contains(CloseRangeFlags::CLOEXEC) {
if let Ok(entry) = file_table_locked.get_entry_mut(fd) {
entry.set_flags(entry.flags() | FdFlags::CLOEXEC);
}
} else if let Some(file) = file_table_locked.close_file(fd) {
files_to_drop.push(file);
}
}
}
drop(files_to_drop);
Ok(SyscallReturn::Return(0))
}

View File

@ -98,6 +98,14 @@ impl<T> Drop for RwArc<T> {
}
}
impl<T: Clone> RwArc<T> {
/// Returns the contained value by cloning it.
pub fn get_cloned(&self) -> T {
let guard = self.read();
guard.clone()
}
}
impl<T> RoArc<T> {
/// Acquires the read lock for immutable access.
pub fn read(&self) -> RwLockReadGuard<T, PreemptDisabled> {

View File

@ -133,7 +133,7 @@ close01
close02
# close_range01
# close_range02
close_range02
confstr01