From fcb9bfc901f30e67a7f5e776600e2cff684c6403 Mon Sep 17 00:00:00 2001 From: lhw2002426 <1466397747@qq.com> Date: Wed, 8 May 2024 18:15:23 +0800 Subject: [PATCH] move fdtable to kernel and add gc flush --- Cargo.lock | 20 ++- Cargo.toml | 1 + api/ruxos_posix_api/Cargo.toml | 1 + api/ruxos_posix_api/src/imp/fd_ops.rs | 132 ++++++++++++++++--- api/ruxos_posix_api/src/imp/fs.rs | 35 +++-- api/ruxos_posix_api/src/imp/io_mpx/epoll.rs | 13 +- api/ruxos_posix_api/src/imp/net.rs | 13 +- api/ruxos_posix_api/src/imp/pipe.rs | 13 +- api/ruxos_posix_api/src/imp/resources.rs | 4 +- api/ruxos_posix_api/src/imp/stdio.rs | 24 ++-- apps/c/helloworld/main.c | 2 +- crates/driver_block/Cargo.toml | 2 +- modules/ruxfdtable/Cargo.toml | 20 +++ modules/ruxfdtable/src/lib.rs | 137 ++++++++++++++++++++ modules/ruxfs/Cargo.toml | 4 +- modules/ruxfs/src/dev.rs | 5 + modules/ruxfs/src/fs/fatfs.rs | 25 +++- modules/ruxtask/Cargo.toml | 2 + modules/ruxtask/src/run_queue.rs | 18 +++ rust-toolchain.toml | 2 +- 20 files changed, 409 insertions(+), 64 deletions(-) create mode 100644 modules/ruxfdtable/Cargo.toml create mode 100644 modules/ruxfdtable/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b53869d52..067d44654 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,7 +249,7 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bcm2835-sdhci" version = "0.1.0" -source = "git+https://github.com/lhw2002426/bcm2835-sdhci.git?rev=bf07a72#bf07a727e07ba3f3f276d9bead2401cdb343d019" +source = "git+https://github.com/syswonder/bcm2835-sdhci.git?rev=e974f16#e974f168efa72b470a01f61bdef32240c66f54fc" dependencies = [ "aarch64-cpu", "log", @@ -784,10 +784,11 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fatfs" version = "0.4.0" -source = "git+https://github.com/rafalh/rust-fatfs?rev=a3a834e#a3a834ef92d94dd227c316c0887654dab00ae085" +source = "git+https://github.com/syswonder/rust-fatfs.git?rev=bf8ad02#bf8ad02bc6060728f6d3b81ee8428d731da4ca94" dependencies = [ "bitflags 1.3.2", "log", + "spin 0.9.8", ] [[package]] @@ -1523,6 +1524,18 @@ dependencies = [ "ruxhal", ] +[[package]] +name = "ruxfdtable" +version = "0.1.0" +dependencies = [ + "axerrno", + "axio", + "flatten_objects", + "lazy_static", + "log", + "spin 0.9.8", +] + [[package]] name = "ruxfeat" version = "0.1.0" @@ -1676,6 +1689,7 @@ dependencies = [ "memory_addr", "page_table", "ruxconfig", + "ruxfdtable", "ruxfeat", "ruxfs", "ruxfutex", @@ -1715,6 +1729,7 @@ dependencies = [ name = "ruxtask" version = "0.1.0" dependencies = [ + "axerrno", "cfg-if", "crate_interface", "kernel_guard", @@ -1724,6 +1739,7 @@ dependencies = [ "percpu", "rand", "ruxconfig", + "ruxfdtable", "ruxhal", "ruxtask", "scheduler", diff --git a/Cargo.toml b/Cargo.toml index 29f519fc3..26aa6c17a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ members = [ "modules/ruxconfig", "modules/ruxdisplay", "modules/ruxdriver", + "modules/ruxfdtable", "modules/ruxfs", "modules/ruxhal", "modules/ruxruntime", diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index b767b2d72..7f4f47d77 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -43,6 +43,7 @@ ruxconfig = { path = "../../modules/ruxconfig" } axlog = { path = "../../modules/axlog" } ruxhal = { path = "../../modules/ruxhal" } axsync = { path = "../../modules/axsync" } +ruxfdtable = { path = "../../modules/ruxfdtable" } ruxfutex = { path = "../../modules/ruxfutex", optional = true } axalloc = { path = "../../modules/axalloc", optional = true } ruxtask = { path = "../../modules/ruxtask", optional = true } diff --git a/api/ruxos_posix_api/src/imp/fd_ops.rs b/api/ruxos_posix_api/src/imp/fd_ops.rs index bb5ca1e43..6f271de17 100644 --- a/api/ruxos_posix_api/src/imp/fd_ops.rs +++ b/api/ruxos_posix_api/src/imp/fd_ops.rs @@ -11,36 +11,130 @@ use alloc::sync::Arc; use core::ffi::c_int; use axerrno::{LinuxError, LinuxResult}; -use axio::PollState; -use flatten_objects::FlattenObjects; -use spin::RwLock; +use ruxfdtable::{FileLike, RuxStat, RuxTimeSpec, FD_TABLE, RUX_FILE_LIMIT}; use super::stdio::{stdin, stdout}; use crate::ctypes; -/// Maximum number of files per process -pub const RUX_FILE_LIMIT: usize = 1024; +impl From for RuxTimeSpec { + fn from(ctimespec: ctypes::timespec) -> Self { + RuxTimeSpec { + tv_sec: ctimespec.tv_sec, + tv_nsec: ctimespec.tv_nsec, + } + } +} + +impl From for RuxStat { + #[cfg(target_arch = "aarch64")] + fn from(cstat: ctypes::stat) -> Self { + RuxStat { + st_dev: cstat.st_dev, + st_ino: cstat.st_ino, + st_mode: cstat.st_mode, + st_nlink: cstat.st_nlink, + st_uid: cstat.st_uid, + st_gid: cstat.st_gid, + st_rdev: cstat.st_rdev, + __pad: cstat.__pad, + st_size: cstat.st_size, + st_blksize: cstat.st_blksize, + __pad2: cstat.__pad2, + st_blocks: cstat.st_blocks, + st_atime: RuxTimeSpec::from(cstat.st_atime), + st_mtime: RuxTimeSpec::from(cstat.st_mtime), + st_ctime: RuxTimeSpec::from(cstat.st_ctime), + __unused: cstat.__unused, + } + } + + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] + fn from(cstat: ctypes::stat) -> Self { + RuxStat { + st_dev: cstat.st_dev, + st_ino: cstat.st_ino, + st_nlink: cstat.st_nlink, + st_mode: cstat.st_mode, + st_uid: cstat.st_uid, + st_gid: cstat.st_gid, + __pad0: cstat.__pad0, + st_rdev: cstat.st_rdev, + st_size: cstat.st_size, + st_blksize: cstat.st_blksize, + st_blocks: cstat.st_blocks, + st_atime: RuxTimeSpec::from(cstat.st_atime), + st_mtime: RuxTimeSpec::from(cstat.st_mtime), + st_ctime: RuxTimeSpec::from(cstat.st_ctime), + __unused: cstat.__unused, + } + } +} -pub trait FileLike: Send + Sync { - fn read(&self, buf: &mut [u8]) -> LinuxResult; - fn write(&self, buf: &[u8]) -> LinuxResult; - fn stat(&self) -> LinuxResult; - fn into_any(self: Arc) -> Arc; - fn poll(&self) -> LinuxResult; - fn set_nonblocking(&self, nonblocking: bool) -> LinuxResult; +impl From for ctypes::timespec { + fn from(rtimespec: RuxTimeSpec) -> Self { + ctypes::timespec { + tv_sec: rtimespec.tv_sec, + tv_nsec: rtimespec.tv_nsec, + } + } +} + +impl From for ctypes::stat { + #[cfg(target_arch = "aarch64")] + fn from(rstat: RuxStat) -> Self { + ctypes::stat { + st_dev: rstat.st_dev, + st_ino: rstat.st_ino, + st_mode: rstat.st_mode, + st_nlink: rstat.st_nlink, + st_uid: rstat.st_uid, + st_gid: rstat.st_gid, + st_rdev: rstat.st_rdev, + __pad: rstat.__pad, + st_size: rstat.st_size, + st_blksize: rstat.st_blksize, + __pad2: rstat.__pad2, + st_blocks: rstat.st_blocks, + st_atime: rstat.st_atime.into(), + st_mtime: rstat.st_mtime.into(), + st_ctime: rstat.st_ctime.into(), + __unused: rstat.__unused, + } + } + + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] + fn from(rstat: RuxStat) -> Self { + ctypes::stat { + st_dev: rstat.st_dev, + st_ino: rstat.st_ino, + st_nlink: rstat.st_nlink, + st_mode: rstat.st_mode, + st_uid: rstat.st_uid, + st_gid: rstat.st_gid, + __pad0: rstat.__pad0, + st_rdev: rstat.st_rdev, + st_size: rstat.st_size, + st_blksize: rstat.st_blksize, + st_blocks: rstat.st_blocks, + st_atime: rstat.st_atime.into(), + st_mtime: rstat.st_mtime.into(), + st_ctime: rstat.st_ctime.into(), + __unused: rstat.__unused, + } + } } lazy_static::lazy_static! { - static ref FD_TABLE: RwLock, RUX_FILE_LIMIT>> = { - let mut fd_table = FlattenObjects::new(); - fd_table.add_at(0, Arc::new(stdin()) as _).unwrap(); // stdin - fd_table.add_at(1, Arc::new(stdout()) as _).unwrap(); // stdout - fd_table.add_at(2, Arc::new(stdout()) as _).unwrap(); // stderr - RwLock::new(fd_table) + static ref MUST_EXEC: usize = { + FD_TABLE.write().add_at(0, Arc::new(stdin()) as _).unwrap(); // stdin + FD_TABLE.write().add_at(1, Arc::new(stdout()) as _).unwrap(); // stdout + FD_TABLE.write().add_at(2, Arc::new(stdout()) as _).unwrap(); // stderr + 0 }; } pub fn get_file_like(fd: c_int) -> LinuxResult> { + let _exec = *MUST_EXEC; FD_TABLE .read() .get(fd as usize) @@ -49,10 +143,12 @@ pub fn get_file_like(fd: c_int) -> LinuxResult> { } pub fn add_file_like(f: Arc) -> LinuxResult { + let _exec = *MUST_EXEC; Ok(FD_TABLE.write().add(f).ok_or(LinuxError::EMFILE)? as c_int) } pub fn close_file_like(fd: c_int) -> LinuxResult { + let _exec = *MUST_EXEC; let f = FD_TABLE .write() .remove(fd as usize) diff --git a/api/ruxos_posix_api/src/imp/fs.rs b/api/ruxos_posix_api/src/imp/fs.rs index 9d47b0624..84d586aa7 100644 --- a/api/ruxos_posix_api/src/imp/fs.rs +++ b/api/ruxos_posix_api/src/imp/fs.rs @@ -13,12 +13,13 @@ use core::ffi::{c_char, c_int, c_long, c_void}; use axerrno::{LinuxError, LinuxResult}; use axio::{PollState, SeekFrom}; use axsync::Mutex; +use ruxfdtable::{FileLike, RuxStat}; use ruxfs::{ api::set_current_dir, fops::{DirEntry, OpenOptions}, }; -use super::fd_ops::{get_file_like, FileLike}; +use super::fd_ops::get_file_like; use crate::{ctypes, utils::char_ptr_to_str}; use alloc::vec::Vec; @@ -54,7 +55,11 @@ impl FileLike for File { Ok(self.inner.lock().write(buf)?) } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(self.inner.lock().flush()?) + } + + fn stat(&self) -> LinuxResult { let metadata = self.inner.lock().get_attr()?; let ty = metadata.file_type() as u8; let perm = metadata.perm().bits() as u32; @@ -65,7 +70,7 @@ impl FileLike for File { // TODO: implement real inode. let st_ino = metadata.size() + st_mode as u64; - Ok(ctypes::stat { + let res = RuxStat::from(ctypes::stat { st_ino, st_nlink: 1, st_mode, @@ -75,7 +80,9 @@ impl FileLike for File { st_blocks: metadata.blocks() as _, st_blksize: 512, ..Default::default() - }) + }); + + Ok(res) } fn into_any(self: Arc) -> Arc { @@ -126,12 +133,16 @@ impl FileLike for Directory { Err(LinuxError::EACCES) } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { let metadata = self.inner.lock().get_attr()?; let ty = metadata.file_type() as u8; let perm = metadata.perm().bits() as u32; let st_mode = ((ty as u32) << 12) | perm; - Ok(ctypes::stat { + Ok(RuxStat::from(ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, @@ -141,7 +152,7 @@ impl FileLike for Directory { st_blocks: metadata.blocks() as _, st_blksize: 512, ..Default::default() - }) + })) } fn into_any(self: Arc) -> Arc { @@ -197,7 +208,8 @@ pub fn sys_open(filename: *const c_char, flags: c_int, mode: ctypes::mode_t) -> syscall_body!(sys_open, { let options = flags_to_options(flags, mode); let file = ruxfs::fops::File::open(filename?, &options)?; - File::new(file).add_to_fd_table() + let res = File::new(file).add_to_fd_table(); + res }) } @@ -227,7 +239,8 @@ pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mo .lock() .open_file_at(path?, &options)? }; - File::new(file).add_to_fd_table() + let res = File::new(file).add_to_fd_table(); + res } }) } @@ -318,7 +331,7 @@ pub unsafe fn sys_stat(path: *const c_char, buf: *mut core::ffi::c_void) -> c_in let mut options = OpenOptions::new(); options.read(true); let file = ruxfs::fops::File::open(path?, &options)?; - let st = File::new(file).stat()?; + let st: ctypes::stat = File::new(file).stat()?.into(); #[cfg(not(feature = "musl"))] { @@ -356,7 +369,7 @@ pub fn sys_fstat(fd: c_int, kst: *mut core::ffi::c_void) -> c_int { #[cfg(not(feature = "musl"))] { let buf = kst as *mut ctypes::stat; - unsafe { *buf = get_file_like(fd)?.stat()? }; + unsafe { *buf = get_file_like(fd)?.stat()?.into() }; Ok(0) } #[cfg(feature = "musl")] diff --git a/api/ruxos_posix_api/src/imp/io_mpx/epoll.rs b/api/ruxos_posix_api/src/imp/io_mpx/epoll.rs index 68c7b8a50..570b7a192 100644 --- a/api/ruxos_posix_api/src/imp/io_mpx/epoll.rs +++ b/api/ruxos_posix_api/src/imp/io_mpx/epoll.rs @@ -18,10 +18,11 @@ use core::{ffi::c_int, time::Duration}; use axerrno::{LinuxError, LinuxResult}; use axsync::Mutex; +use ruxfdtable::{FileLike, RuxStat}; use ruxhal::time::current_time; use crate::ctypes; -use crate::imp::fd_ops::{add_file_like, get_file_like, FileLike}; +use crate::imp::fd_ops::{add_file_like, get_file_like}; pub struct EpollInstance { events: Mutex>, @@ -123,14 +124,18 @@ impl FileLike for EpollInstance { Err(LinuxError::ENOSYS) } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { let st_mode = 0o600u32; // rw------- - Ok(ctypes::stat { + Ok(RuxStat::from(ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, ..Default::default() - }) + })) } fn into_any(self: Arc) -> alloc::sync::Arc { diff --git a/api/ruxos_posix_api/src/imp/net.rs b/api/ruxos_posix_api/src/imp/net.rs index 56cb8b6a1..144f1c80c 100644 --- a/api/ruxos_posix_api/src/imp/net.rs +++ b/api/ruxos_posix_api/src/imp/net.rs @@ -16,8 +16,8 @@ use axerrno::{LinuxError, LinuxResult}; use axio::PollState; use axnet::{TcpSocket, UdpSocket}; use axsync::Mutex; +use ruxfdtable::{FileLike, RuxStat}; -use super::fd_ops::FileLike; use crate::ctypes; use crate::utils::char_ptr_to_str; @@ -148,10 +148,15 @@ impl FileLike for Socket { self.send(buf) } - fn stat(&self) -> LinuxResult { + ///TODO + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { // not really implemented let st_mode = 0o140000 | 0o777u32; // S_IFSOCK | rwxrwxrwx - Ok(ctypes::stat { + Ok(RuxStat::from(ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, @@ -159,7 +164,7 @@ impl FileLike for Socket { st_gid: 1000, st_blksize: 4096, ..Default::default() - }) + })) } fn into_any(self: Arc) -> Arc { diff --git a/api/ruxos_posix_api/src/imp/pipe.rs b/api/ruxos_posix_api/src/imp/pipe.rs index 1638d89c8..7a67120ff 100644 --- a/api/ruxos_posix_api/src/imp/pipe.rs +++ b/api/ruxos_posix_api/src/imp/pipe.rs @@ -13,8 +13,9 @@ use core::ffi::c_int; use axerrno::{LinuxError, LinuxResult}; use axio::PollState; use axsync::Mutex; +use ruxfdtable::{FileLike, RuxStat}; -use super::fd_ops::{add_file_like, close_file_like, FileLike}; +use super::fd_ops::{add_file_like, close_file_like}; use crate::{ctypes, sys_fcntl}; #[derive(Copy, Clone, PartialEq)] @@ -181,9 +182,13 @@ impl FileLike for Pipe { } } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { let st_mode = 0o10000 | 0o600u32; // S_IFIFO | rw------- - Ok(ctypes::stat { + Ok(RuxStat::from(ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, @@ -191,7 +196,7 @@ impl FileLike for Pipe { st_gid: 1000, st_blksize: 4096, ..Default::default() - }) + })) } fn into_any(self: Arc) -> Arc { diff --git a/api/ruxos_posix_api/src/imp/resources.rs b/api/ruxos_posix_api/src/imp/resources.rs index eec2f6751..f3e05da73 100644 --- a/api/ruxos_posix_api/src/imp/resources.rs +++ b/api/ruxos_posix_api/src/imp/resources.rs @@ -56,8 +56,8 @@ pub unsafe fn sys_getrlimit(resource: c_int, rlimits: *mut ctypes::rlimit) -> c_ }, #[cfg(feature = "fd")] ctypes::RLIMIT_NOFILE => unsafe { - (*rlimits).rlim_cur = super::fd_ops::RUX_FILE_LIMIT as _; - (*rlimits).rlim_max = super::fd_ops::RUX_FILE_LIMIT as _; + (*rlimits).rlim_cur = ruxfdtable::RUX_FILE_LIMIT as _; + (*rlimits).rlim_max = ruxfdtable::RUX_FILE_LIMIT as _; }, ctypes::RLIMIT_MEMLOCK => {} ctypes::RLIMIT_AS => {} diff --git a/api/ruxos_posix_api/src/imp/stdio.rs b/api/ruxos_posix_api/src/imp/stdio.rs index 7b9699154..1a87669c7 100644 --- a/api/ruxos_posix_api/src/imp/stdio.rs +++ b/api/ruxos_posix_api/src/imp/stdio.rs @@ -133,7 +133,7 @@ pub fn stdout() -> Stdout { } #[cfg(feature = "fd")] -impl super::fd_ops::FileLike for Stdin { +impl ruxfdtable::FileLike for Stdin { fn read(&self, buf: &mut [u8]) -> LinuxResult { match self.nonblocking.load(Ordering::Relaxed) { true => Ok(self.read_nonblocked(buf)?), @@ -145,14 +145,18 @@ impl super::fd_ops::FileLike for Stdin { Err(LinuxError::EPERM) } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { let st_mode = 0o20000 | 0o440u32; // S_IFCHR | r--r----- - Ok(crate::ctypes::stat { + Ok(ruxfdtable::RuxStat::from(crate::ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, ..Default::default() - }) + })) } fn into_any(self: Arc) -> Arc { @@ -173,7 +177,7 @@ impl super::fd_ops::FileLike for Stdin { } #[cfg(feature = "fd")] -impl super::fd_ops::FileLike for Stdout { +impl ruxfdtable::FileLike for Stdout { fn read(&self, _buf: &mut [u8]) -> LinuxResult { Err(LinuxError::EPERM) } @@ -182,14 +186,18 @@ impl super::fd_ops::FileLike for Stdout { Ok(self.inner.lock().write(buf)?) } - fn stat(&self) -> LinuxResult { + fn flush(&self) -> LinuxResult { + Ok(()) + } + + fn stat(&self) -> LinuxResult { let st_mode = 0o20000 | 0o220u32; // S_IFCHR | -w--w---- - Ok(crate::ctypes::stat { + Ok(ruxfdtable::RuxStat::from(crate::ctypes::stat { st_ino: 1, st_nlink: 1, st_mode, ..Default::default() - }) + })) } fn into_any(self: Arc) -> Arc { diff --git a/apps/c/helloworld/main.c b/apps/c/helloworld/main.c index b64a16128..3dddbeff9 100644 --- a/apps/c/helloworld/main.c +++ b/apps/c/helloworld/main.c @@ -13,4 +13,4 @@ int main() { printf("Hello, %c app!\n", 'C'); return 0; -} +} \ No newline at end of file diff --git a/crates/driver_block/Cargo.toml b/crates/driver_block/Cargo.toml index c66f8763c..a264145e7 100644 --- a/crates/driver_block/Cargo.toml +++ b/crates/driver_block/Cargo.toml @@ -17,4 +17,4 @@ default = [] [dependencies] log = "0.4" driver_common = { path = "../driver_common" } -bcm2835-sdhci = { git = "https://github.com/lhw2002426/bcm2835-sdhci.git", rev = "bf07a72", optional = true } +bcm2835-sdhci = { git = "https://github.com/syswonder/bcm2835-sdhci.git", rev = "e974f16", optional = true } diff --git a/modules/ruxfdtable/Cargo.toml b/modules/ruxfdtable/Cargo.toml new file mode 100644 index 000000000..a6caffe40 --- /dev/null +++ b/modules/ruxfdtable/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "ruxfdtable" +version = "0.1.0" +edition = "2021" +authors = ["HaoWen Liu "] +description = "fd table for ruxos file system" +license = "GPL-3.0-or-later OR Apache-2.0" +homepage = "https://github.com/syswonder/ruxos" +repository = "https://github.com/syswonder/ruxos/tree/main/crates/ruxfdtable" + +[features] +default = [] + +[dependencies] +log = "0.4" +spin = "0.9" +axio = { path = "../../crates/axio" } +lazy_static = { version = "1.4", features = ["spin_no_std"] } +flatten_objects = { path = "../../crates/flatten_objects" } +axerrno = { path = "../../crates/axerrno" } diff --git a/modules/ruxfdtable/src/lib.rs b/modules/ruxfdtable/src/lib.rs new file mode 100644 index 000000000..8daf26fa4 --- /dev/null +++ b/modules/ruxfdtable/src/lib.rs @@ -0,0 +1,137 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +//! fd table and FileLike trait for file system +#![no_std] +extern crate alloc; +use alloc::sync::Arc; +use core::marker::Send; +use core::marker::Sync; + +use axerrno::LinuxResult; +use axio::PollState; +use flatten_objects::FlattenObjects; +use spin::RwLock; + +///Rust version for struct timespec in ctypes. Represents a high-resolution time specification. +pub struct RuxTimeSpec { + /// Whole seconds part of the timespec. + pub tv_sec: core::ffi::c_longlong, + /// Nanoseconds part of the timespec, complementing `tv_sec`. + pub tv_nsec: core::ffi::c_long, +} + +///Rust version for struct stat in ctypes. Represents file status information. +#[cfg(target_arch = "aarch64")] +pub struct RuxStat { + /// Device identifier. + pub st_dev: u64, + /// Inode number. + pub st_ino: u64, + /// File mode and permissions. + pub st_mode: core::ffi::c_uint, + /// Number of hard links. + pub st_nlink: u32, + /// User ID of owner. + pub st_uid: core::ffi::c_uint, + /// Group ID of owner. + pub st_gid: core::ffi::c_uint, + /// Device ID (if special file). + pub st_rdev: u64, + /// Padding to maintain alignment. + pub __pad: core::ffi::c_ulong, + /// Total size, in bytes. + pub st_size: i64, + /// Block size for filesystem I/O. + pub st_blksize: core::ffi::c_long, + /// Padding to maintain alignment. + pub __pad2: core::ffi::c_int, + /// Number of 512B blocks allocated. + pub st_blocks: i64, + /// Time of last access. + pub st_atime: RuxTimeSpec, + /// Time of last modification. + pub st_mtime: RuxTimeSpec, + /// Time of last status change. + pub st_ctime: RuxTimeSpec, + /// Unused space, reserved for future use. + pub __unused: [core::ffi::c_uint; 2usize], +} +///Rust version for struct stat in ctypes. Represents file status information. +#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] +pub struct RuxStat { + /// Device identifier. + pub st_dev: u64, + /// Inode number. + pub st_ino: u64, + /// Number of hard links. + pub st_nlink: u64, + /// File mode and permissions. + pub st_mode: core::ffi::c_uint, + /// User ID of owner. + pub st_uid: core::ffi::c_uint, + /// Group ID of owner. + pub st_gid: core::ffi::c_uint, + /// Padding to maintain alignment. + pub __pad0: core::ffi::c_uint, + /// Device ID (if special file). + pub st_rdev: u64, + /// Total size, in bytes. + pub st_size: i64, + /// Block size for filesystem I/O. + pub st_blksize: core::ffi::c_long, + /// Number of 512B blocks allocated. + pub st_blocks: i64, + /// Time of last access. + pub st_atime: RuxTimeSpec, + /// Time of last modification. + pub st_mtime: RuxTimeSpec, + /// Time of last status change. + pub st_ctime: RuxTimeSpec, + /// Unused space, reserved for future use. + pub __unused: [core::ffi::c_long; 3usize], +} + +/// Trait for file-like objects in a file descriptor table. +pub trait FileLike: Send + Sync { + /// Reads data from the file-like object into the provided buffer. + /// + /// Returns the number of bytes read on success. + fn read(&self, buf: &mut [u8]) -> LinuxResult; + + /// Writes data from the provided buffer to the file-like object. + /// + /// Returns the number of bytes written on success. + fn write(&self, buf: &[u8]) -> LinuxResult; + + /// Flushes any buffered data to the file-like object. + fn flush(&self) -> LinuxResult; + + /// Retrieves metadata about the file-like object. + fn stat(&self) -> LinuxResult; + + /// Converts this object into a generic `Any` type, enabling downcasting. + fn into_any(self: Arc) -> Arc; + + /// Polls the file-like object for readiness events. + fn poll(&self) -> LinuxResult; + + /// Sets or clears the non-blocking I/O mode for the file-like object. + fn set_nonblocking(&self, nonblocking: bool) -> LinuxResult; +} +/// Maximum number of files per process +pub const RUX_FILE_LIMIT: usize = 1024; + +lazy_static::lazy_static! { + /// Global file descriptor table protected by a read-write lock. + pub static ref FD_TABLE: RwLock, RUX_FILE_LIMIT>> = { + let mut fd_table = FlattenObjects::new(); + RwLock::new(fd_table) + }; +} diff --git a/modules/ruxfs/Cargo.toml b/modules/ruxfs/Cargo.toml index 91d3356c7..38d7ef6e5 100644 --- a/modules/ruxfs/Cargo.toml +++ b/modules/ruxfs/Cargo.toml @@ -43,8 +43,8 @@ axalloc = { path = "../axalloc", optional = true } memory_addr = { path = "../../crates/memory_addr" } [dependencies.fatfs] -git = "https://github.com/rafalh/rust-fatfs" -rev = "a3a834e" +git = "https://github.com/syswonder/rust-fatfs.git" +rev = "bf8ad02" optional = true default-features = false features = [ # no std diff --git a/modules/ruxfs/src/dev.rs b/modules/ruxfs/src/dev.rs index d0d8ea201..f897c4c76 100644 --- a/modules/ruxfs/src/dev.rs +++ b/modules/ruxfs/src/dev.rs @@ -98,4 +98,9 @@ impl Disk { }; Ok(write_size) } + + ///flush device cache + pub fn do_flush(&mut self) -> DevResult { + self.dev.flush() + } } diff --git a/modules/ruxfs/src/fs/fatfs.rs b/modules/ruxfs/src/fs/fatfs.rs index 102b59afb..3b27b7f6f 100644 --- a/modules/ruxfs/src/fs/fatfs.rs +++ b/modules/ruxfs/src/fs/fatfs.rs @@ -74,6 +74,10 @@ impl FatFileSystem { impl VfsNodeOps for FileWrapper<'static> { axfs_vfs::impl_vfs_non_dir_default! {} + fn fsync(&self) -> VfsResult { + self.0.lock().flush().map_err(as_vfs_err) + } + fn get_attr(&self) -> VfsResult { let size = self.0.lock().seek(SeekFrom::End(0)).map_err(as_vfs_err)?; let blocks = (size + BLOCK_SIZE as u64 - 1) / BLOCK_SIZE as u64; @@ -150,11 +154,20 @@ impl VfsNodeOps for DirWrapper<'static> { return self.lookup(rest); } - // TODO: use `fatfs::Dir::find_entry`, but it's not public. - if let Ok(file) = self.0.open_file(path) { - Ok(FatFileSystem::new_file(file)) - } else if let Ok(dir) = self.0.open_dir(path) { - Ok(FatFileSystem::new_dir(dir)) + if let Ok(Some(is_dir)) = self.0.check_path_type(path) { + if is_dir { + if let Ok(dir) = self.0.open_dir(path) { + Ok(FatFileSystem::new_dir(dir)) + } else { + Err(VfsError::NotADirectory) + } + } else { + if let Ok(file) = self.0.open_file(path) { + Ok(FatFileSystem::new_file(file)) + } else { + Err(VfsError::IsADirectory) + } + } } else { Err(VfsError::NotFound) } @@ -272,7 +285,7 @@ impl Write for Disk { Ok(write_len) } fn flush(&mut self) -> Result<(), Self::Error> { - Ok(()) + self.do_flush().map_err(|_| ()) } } diff --git a/modules/ruxtask/Cargo.toml b/modules/ruxtask/Cargo.toml index a2227c092..ffdf10057 100644 --- a/modules/ruxtask/Cargo.toml +++ b/modules/ruxtask/Cargo.toml @@ -32,8 +32,10 @@ test = ["percpu?/sp-naive"] [dependencies] cfg-if = "1.0" log = "0.4" +axerrno = { path = "../../crates/axerrno" } ruxhal = { path = "../ruxhal" } ruxconfig = { path = "../ruxconfig", optional = true } +ruxfdtable = { path = "../ruxfdtable" } percpu = { path = "../../crates/percpu", optional = true } spinlock = { path = "../../crates/spinlock", optional = true } lazy_init = { path = "../../crates/lazy_init", optional = true } diff --git a/modules/ruxtask/src/run_queue.rs b/modules/ruxtask/src/run_queue.rs index d4fa3613d..5e98942de 100644 --- a/modules/ruxtask/src/run_queue.rs +++ b/modules/ruxtask/src/run_queue.rs @@ -9,7 +9,9 @@ use alloc::collections::VecDeque; use alloc::sync::Arc; +use axerrno::{LinuxError, LinuxResult}; use lazy_init::LazyInit; +use ruxfdtable::{FD_TABLE, RUX_FILE_LIMIT}; use scheduler::BaseScheduler; use spinlock::SpinNoIrq; @@ -202,8 +204,24 @@ impl AxRunQueue { } } +fn gc_flush_file(fd: usize) -> LinuxResult { + trace!("gc task flush: {}", fd); + FD_TABLE + .read() + .get(fd) + .cloned() + .ok_or(LinuxError::EBADF)? + .flush() +} + fn gc_entry() { + let mut now_file_fd: usize = 3; loop { + let _ = gc_flush_file(now_file_fd); + now_file_fd += 1; + if now_file_fd >= RUX_FILE_LIMIT { + now_file_fd = 3; + } // Drop all exited tasks and recycle resources. let n = EXITED_TASKS.lock().len(); for _ in 0..n { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e4a809167..b789cc033 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] profile = "minimal" -channel = "nightly-2023-09-01" +channel = "nightly-2023-12-01" components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"] targets = ["x86_64-unknown-none", "riscv64gc-unknown-none-elf", "aarch64-unknown-none-softfloat"]