mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-19 12:36:46 +00:00
Rewrite FileTable with SlotVec
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
0abe40e0f8
commit
c3152c4978
@ -23,14 +23,14 @@ enum Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FileHandle {
|
impl FileHandle {
|
||||||
pub fn new_file(file: Arc<dyn File>) -> Self {
|
pub fn new_file(file: Arc<dyn File>) -> Arc<Self> {
|
||||||
let inner = Inner::File(file);
|
let inner = Inner::File(file);
|
||||||
Self { inner }
|
Arc::new(Self { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_inode_handle(inode_handle: InodeHandle) -> Self {
|
pub fn new_inode_handle(inode_handle: InodeHandle) -> Arc<Self> {
|
||||||
let inner = Inner::Inode(inode_handle);
|
let inner = Inner::Inode(inode_handle);
|
||||||
Self { inner }
|
Arc::new(Self { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_file(&self) -> Option<&Arc<dyn File>> {
|
pub fn as_file(&self) -> Option<&Arc<dyn File>> {
|
||||||
|
@ -1,92 +1,115 @@
|
|||||||
use crate::events::{Events, Observer, Subject};
|
use crate::events::{Events, Observer, Subject};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use core::cell::Cell;
|
||||||
|
use jinux_util::slot_vec::SlotVec;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
file_handle::FileHandle,
|
file_handle::FileHandle,
|
||||||
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
stdio::{Stderr, Stdin, Stdout},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type FileDescripter = i32;
|
pub type FileDescripter = i32;
|
||||||
|
|
||||||
pub struct FileTable {
|
pub struct FileTable {
|
||||||
table: BTreeMap<FileDescripter, FileHandle>,
|
table: SlotVec<FileTableEntry>,
|
||||||
subject: Subject<FdEvents>,
|
subject: Subject<FdEvents>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileTable {
|
impl FileTable {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
table: BTreeMap::new(),
|
table: SlotVec::new(),
|
||||||
subject: Subject::new(),
|
subject: Subject::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_stdio() -> Self {
|
pub fn new_with_stdio() -> Self {
|
||||||
let mut table = BTreeMap::new();
|
let mut table = SlotVec::new();
|
||||||
let stdin = Stdin::new_with_default_console();
|
let stdin = Stdin::new_with_default_console();
|
||||||
let stdout = Stdout::new_with_default_console();
|
let stdout = Stdout::new_with_default_console();
|
||||||
let stderr = Stderr::new_with_default_console();
|
let stderr = Stderr::new_with_default_console();
|
||||||
table.insert(FD_STDIN, FileHandle::new_file(Arc::new(stdin)));
|
table.put(FileTableEntry::new(
|
||||||
table.insert(FD_STDOUT, FileHandle::new_file(Arc::new(stdout)));
|
FileHandle::new_file(Arc::new(stdin)),
|
||||||
table.insert(FD_STDERR, FileHandle::new_file(Arc::new(stderr)));
|
false,
|
||||||
|
));
|
||||||
|
table.put(FileTableEntry::new(
|
||||||
|
FileHandle::new_file(Arc::new(stdout)),
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
table.put(FileTableEntry::new(
|
||||||
|
FileHandle::new_file(Arc::new(stderr)),
|
||||||
|
false,
|
||||||
|
));
|
||||||
Self {
|
Self {
|
||||||
table,
|
table,
|
||||||
subject: Subject::new(),
|
subject: Subject::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dup(&mut self, fd: FileDescripter, new_fd: Option<FileDescripter>) -> Result<()> {
|
pub fn dup(&mut self, fd: FileDescripter, new_fd: FileDescripter) -> Result<FileDescripter> {
|
||||||
let file = self.table.get(&fd).map_or_else(
|
let entry = self.table.get(fd as usize).map_or_else(
|
||||||
|| return_errno_with_message!(Errno::ENOENT, "No such file"),
|
|| return_errno_with_message!(Errno::ENOENT, "No such file"),
|
||||||
|f| Ok(f.clone()),
|
|e| Ok(e.clone()),
|
||||||
)?;
|
)?;
|
||||||
let new_fd = if let Some(new_fd) = new_fd {
|
|
||||||
new_fd
|
// Get the lowest-numbered available fd equal to or greater than `new_fd`.
|
||||||
} else {
|
let get_min_free_fd = || -> usize {
|
||||||
self.max_fd() + 1
|
let new_fd = new_fd as usize;
|
||||||
|
if self.table.get(new_fd).is_none() {
|
||||||
|
return new_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx in new_fd + 1..self.table.slots_len() {
|
||||||
|
if self.table.get(idx).is_none() {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.table.slots_len()
|
||||||
};
|
};
|
||||||
if self.table.contains_key(&new_fd) {
|
|
||||||
return_errno_with_message!(Errno::EBADF, "Fd exists");
|
|
||||||
}
|
|
||||||
self.table.insert(new_fd, file);
|
|
||||||
|
|
||||||
Ok(())
|
let min_free_fd = get_min_free_fd();
|
||||||
|
self.table.put_at(min_free_fd, entry);
|
||||||
|
Ok(min_free_fd as FileDescripter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max_fd(&self) -> FileDescripter {
|
pub fn insert(&mut self, item: Arc<FileHandle>) -> FileDescripter {
|
||||||
self.table.iter().map(|(fd, _)| fd.clone()).max().unwrap()
|
let entry = FileTableEntry::new(item, false);
|
||||||
|
self.table.put(entry) as FileDescripter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, item: FileHandle) -> FileDescripter {
|
pub fn insert_at(
|
||||||
let fd = self.max_fd() + 1;
|
&mut self,
|
||||||
self.table.insert(fd, item);
|
fd: FileDescripter,
|
||||||
fd
|
item: Arc<FileHandle>,
|
||||||
}
|
) -> Option<Arc<FileHandle>> {
|
||||||
|
let entry = FileTableEntry::new(item, false);
|
||||||
pub fn insert_at(&mut self, fd: FileDescripter, item: FileHandle) -> Option<FileHandle> {
|
let entry = self.table.put_at(fd as usize, entry);
|
||||||
let file = self.table.insert(fd, item);
|
if entry.is_some() {
|
||||||
if file.is_some() {
|
|
||||||
self.notify_close_fd_event(fd);
|
self.notify_close_fd_event(fd);
|
||||||
}
|
}
|
||||||
file
|
entry.map(|e| e.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_file(&mut self, fd: FileDescripter) -> Option<FileHandle> {
|
pub fn close_file(&mut self, fd: FileDescripter) -> Option<Arc<FileHandle>> {
|
||||||
let file = self.table.remove(&fd);
|
let entry = self.table.remove(fd as usize);
|
||||||
if file.is_some() {
|
if entry.is_some() {
|
||||||
self.notify_close_fd_event(fd);
|
self.notify_close_fd_event(fd);
|
||||||
}
|
}
|
||||||
file
|
entry.map(|e| e.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_file(&self, fd: FileDescripter) -> Result<&FileHandle> {
|
pub fn get_file(&self, fd: FileDescripter) -> Result<&Arc<FileHandle>> {
|
||||||
self.table
|
self.table
|
||||||
.get(&fd)
|
.get(fd as usize)
|
||||||
|
.map(|entry| &entry.file)
|
||||||
.ok_or(Error::with_message(Errno::EBADF, "fd not exits"))
|
.ok_or(Error::with_message(Errno::EBADF, "fd not exits"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fds_and_files(&self) -> impl Iterator<Item = (&'_ FileDescripter, &'_ FileHandle)> {
|
pub fn fds_and_files(&self) -> impl Iterator<Item = (FileDescripter, &'_ Arc<FileHandle>)> {
|
||||||
self.table.iter()
|
self.table
|
||||||
|
.idxes_and_items()
|
||||||
|
.map(|(idx, entry)| (idx as FileDescripter, &entry.file))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_observer(&self, observer: Weak<dyn Observer<FdEvents>>) {
|
pub fn register_observer(&self, observer: Weak<dyn Observer<FdEvents>>) {
|
||||||
@ -126,3 +149,18 @@ pub enum FdEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Events for FdEvents {}
|
impl Events for FdEvents {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct FileTableEntry {
|
||||||
|
file: Arc<FileHandle>,
|
||||||
|
close_on_exec: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileTableEntry {
|
||||||
|
pub fn new(file: Arc<FileHandle>, close_on_exec: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
file,
|
||||||
|
close_on_exec: Cell::new(close_on_exec),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -62,10 +62,10 @@ impl DirOps for FdDirOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the inode at `/proc/[pid]/fd/N`.
|
/// Represents the inode at `/proc/[pid]/fd/N`.
|
||||||
struct FileSymOps(FileHandle);
|
struct FileSymOps(Arc<FileHandle>);
|
||||||
|
|
||||||
impl FileSymOps {
|
impl FileSymOps {
|
||||||
pub fn new_inode(file: FileHandle, parent: Weak<dyn Inode>) -> Arc<dyn Inode> {
|
pub fn new_inode(file: Arc<FileHandle>, parent: Weak<dyn Inode>) -> Arc<dyn Inode> {
|
||||||
ProcSymBuilder::new(Self(file))
|
ProcSymBuilder::new(Self(file))
|
||||||
.parent(parent)
|
.parent(parent)
|
||||||
.build()
|
.build()
|
||||||
|
@ -12,8 +12,7 @@ pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn
|
|||||||
// FIXME: deal with the cloexec flag
|
// FIXME: deal with the cloexec flag
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let mut file_table = current.file_table().lock();
|
let mut file_table = current.file_table().lock();
|
||||||
let new_fd = arg as FileDescripter;
|
let new_fd = file_table.dup(fd, arg as FileDescripter)?;
|
||||||
file_table.dup(fd, Some(new_fd))?;
|
|
||||||
return Ok(SyscallReturn::Return(new_fd as _));
|
return Ok(SyscallReturn::Return(new_fd as _));
|
||||||
}
|
}
|
||||||
FcntlCmd::F_SETFD => {
|
FcntlCmd::F_SETFD => {
|
||||||
|
Reference in New Issue
Block a user