Merge pull request #71 from liqinggd/dev-fs-impl

Enhance the fs code in std
This commit is contained in:
Tate, Hongliang Tian 2023-02-15 21:53:43 +08:00 committed by GitHub
commit 551406b9f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 261 additions and 210 deletions

View File

@ -2,10 +2,7 @@ use crate::prelude::*;
use crate::tty::get_n_tty;
use core::any::Any;
use super::events::IoEvents;
use super::ioctl::IoctlCmd;
pub type FileDescripter = i32;
use crate::fs::utils::{IoEvents, IoctlCmd};
/// The basic operations defined on a file
pub trait File: Send + Sync + Any {

View File

@ -1,5 +1,4 @@
use crate::prelude::*;
use crate::rights::{Rights, TRights};
use super::*;
@ -10,7 +9,7 @@ impl InodeHandle<Rights> {
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Result<Self> {
let inode_info = dentry.inode().raw_inode().metadata();
let inode_info = dentry.vnode().inode().metadata();
if access_mode.is_readable() && !inode_info.mode.is_readable() {
return_errno_with_message!(Errno::EACCES, "File is not readable");
}

View File

@ -1,9 +1,9 @@
//! Opend File Handle
//! Opend Inode-backed File Handle
mod dyn_cap;
mod static_cap;
use super::utils::{
use crate::fs::utils::{
AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags,
};
use crate::prelude::*;
@ -23,17 +23,17 @@ struct InodeHandle_ {
impl InodeHandle_ {
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
let mut offset = self.offset.lock();
let file_size = self.dentry.inode().raw_inode().metadata().size;
let file_size = self.dentry.vnode().inode().metadata().size;
let start = file_size.min(*offset);
let end = file_size.min(*offset + buf.len());
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
self.dentry
.vnode()
.inode()
.raw_inode()
.read_at(start, &mut buf[0..end - start])?
} else {
self.dentry
.inode()
.vnode()
.pages()
.read_bytes(start, &mut buf[0..end - start])?;
end - start
@ -45,24 +45,21 @@ impl InodeHandle_ {
pub fn write(&self, buf: &[u8]) -> Result<usize> {
let mut offset = self.offset.lock();
let file_size = self.dentry.inode().raw_inode().metadata().size;
let file_size = self.dentry.vnode().inode().metadata().size;
if self.status_flags.lock().contains(StatusFlags::O_APPEND) {
*offset = file_size;
}
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().raw_inode().write_at(*offset, buf)?
self.dentry.vnode().inode().write_at(*offset, buf)?
} else {
let pages = self.dentry.inode().pages();
let pages = self.dentry.vnode().pages();
let should_expand_size = *offset + buf.len() > file_size;
if should_expand_size {
pages.resize(*offset + buf.len())?;
}
pages.write_bytes(*offset, buf)?;
if should_expand_size {
self.dentry
.inode()
.raw_inode()
.resize(*offset + buf.len())?;
self.dentry.vnode().inode().resize(*offset + buf.len())?;
}
buf.len()
};
@ -81,7 +78,7 @@ impl InodeHandle_ {
off as i64
}
SeekFrom::End(off /* as i64 */) => {
let file_size = self.dentry.inode().raw_inode().metadata().size as i64;
let file_size = self.dentry.vnode().inode().metadata().size as i64;
assert!(file_size >= 0);
file_size
.checked_add(off)
@ -128,11 +125,7 @@ impl InodeHandle_ {
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
let mut offset = self.offset.lock();
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
let written_size = self
.dentry
.inode()
.raw_inode()
.readdir(&mut dir_writer_ctx)?;
let written_size = self.dentry.vnode().inode().readdir(&mut dir_writer_ctx)?;
*offset = dir_writer_ctx.pos();
Ok(written_size)
}

View File

@ -1,9 +1,14 @@
//! Opend File Handle
mod file;
mod inode_handle;
use crate::prelude::*;
use crate::rights::{ReadOp, WriteOp};
use alloc::sync::Arc;
use super::file::File;
use super::inode_handle::InodeHandle;
pub use self::file::File;
pub use self::inode_handle::InodeHandle;
#[derive(Clone)]
pub struct FileHandle {

View File

@ -1,11 +1,12 @@
use crate::prelude::*;
use super::{
file::FileDescripter,
file_handle::FileHandle,
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
};
pub type FileDescripter = i32;
#[derive(Clone)]
pub struct FileTable {
table: BTreeMap<FileDescripter, FileHandle>,

View File

@ -2,14 +2,13 @@ use crate::prelude::*;
use alloc::str;
use alloc::string::String;
use super::file::FileDescripter;
use super::inode_handle::InodeHandle;
use super::file_handle::InodeHandle;
use super::file_table::FileDescripter;
use super::ramfs::RamFS;
use super::utils::{
AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, PATH_MAX,
SYMLINKS_MAX,
AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, Vnode,
PATH_MAX, SYMLINKS_MAX,
};
use super::vfs_inode::VfsInode;
lazy_static! {
static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new();
@ -32,8 +31,8 @@ impl Clone for FsResolver {
impl FsResolver {
pub fn new() -> Result<Self> {
let root = {
let root_inode = VfsInode::new(ROOT_FS.root_inode())?;
Dentry::new_root(root_inode)
let root_vnode = Vnode::new(ROOT_FS.root_inode())?;
Dentry::new_root(root_vnode)
};
Ok(Self {
root: root.clone(),
@ -64,9 +63,9 @@ impl FsResolver {
let inode_mode = InodeMode::from_bits_truncate(mode);
let follow_tail_link = !creation_flags.contains(CreationFlags::O_NOFOLLOW);
let dentry = match self.lookup(path, follow_tail_link) {
let dentry = match self.lookup_inner(path, follow_tail_link) {
Ok(dentry) => {
let inode = dentry.inode().raw_inode();
let inode = dentry.vnode().inode();
if inode.metadata().type_ == InodeType::SymLink
&& !status_flags.contains(StatusFlags::O_PATH)
{
@ -94,15 +93,15 @@ impl FsResolver {
if creation_flags.contains(CreationFlags::O_DIRECTORY) {
return_errno_with_message!(Errno::ENOTDIR, "cannot create directory");
}
let (dir_dentry, file_name) = self.lookup_dir_and_base_name(path)?;
let (dir_dentry, file_name) =
self.lookup_dir_and_base_name_inner(path, follow_tail_link)?;
if file_name.ends_with("/") {
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
}
if !dir_dentry.inode().raw_inode().metadata().mode.is_writable() {
if !dir_dentry.vnode().inode().metadata().mode.is_writable() {
return_errno_with_message!(Errno::EPERM, "file cannot be created");
}
let new_dentry =
dir_dentry.create_child(&file_name, InodeType::File, inode_mode)?;
let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?;
new_dentry
}
Err(e) => return Err(e),
@ -112,8 +111,17 @@ impl FsResolver {
Ok(inode_handle)
}
/// Lookup dentry according to FsPath
pub fn lookup(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
/// Lookup dentry according to FsPath, always follow symlinks
pub fn lookup(&self, path: &FsPath) -> Result<Arc<Dentry>> {
self.lookup_inner(path, true)
}
/// Lookup dentry according to FsPath, do not follow it if last component is a symlink
pub fn lookup_no_follow(&self, path: &FsPath) -> Result<Arc<Dentry>> {
self.lookup_inner(path, false)
}
fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
let dentry = match path.inner {
FsPathInner::Absolute(path) => {
self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)?
@ -123,75 +131,15 @@ impl FsResolver {
}
FsPathInner::Cwd => self.cwd.clone(),
FsPathInner::FdRelative(fd, path) => {
let parent = self.lookup_dentry_from_fd(fd)?;
let parent = self.lookup_from_fd(fd)?;
self.lookup_from_parent(&parent, path, follow_tail_link)?
}
FsPathInner::Fd(fd) => self.lookup_dentry_from_fd(fd)?,
FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?,
};
Ok(dentry)
}
/// Lookup the dir dentry and base file name of the giving path.
///
/// If encounters symlinks, should deference them.
fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<Dentry>, String)> {
let (mut dir_dentry, mut base_name) = match path.inner {
FsPathInner::Absolute(path) => {
let (dir, file_name) = split_path(path);
(
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?,
String::from(file_name),
)
}
FsPathInner::CwdRelative(path) => {
let (dir, file_name) = split_path(path);
(
self.lookup_from_parent(&self.cwd, path, true)?,
String::from(file_name),
)
}
FsPathInner::FdRelative(fd, path) => {
let (dir, file_name) = split_path(path);
let parent = self.lookup_dentry_from_fd(fd)?;
(
self.lookup_from_parent(&parent, path, true)?,
String::from(file_name),
)
}
_ => return_errno!(Errno::ENOENT),
};
loop {
match dir_dentry.get(&base_name.trim_end_matches('/')) {
Ok(dentry) if dentry.inode().raw_inode().metadata().type_ == InodeType::SymLink => {
let link = {
let mut link = dentry.inode().raw_inode().read_link()?;
if link.is_empty() {
return_errno_with_message!(Errno::ENOENT, "invalid symlink");
}
if base_name.ends_with("/") && !link.ends_with("/") {
link += "/";
}
link
};
let (dir, file_name) = split_path(&link);
if dir.starts_with("/") {
dir_dentry =
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?;
base_name = String::from(file_name);
} else {
dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?;
base_name = String::from(file_name);
}
}
_ => break,
}
}
Ok((dir_dentry, base_name))
}
/// Lookup dentry from parent
///
/// The length of `path` cannot exceed PATH_MAX.
@ -232,8 +180,8 @@ impl FsResolver {
};
// Iterate next dentry
let next_dentry = dentry.get(next_name)?;
let next_type = next_dentry.inode().raw_inode().metadata().type_;
let next_dentry = dentry.lookup(next_name)?;
let next_type = next_dentry.vnode().inode().metadata().type_;
let next_is_tail = path_remain.is_empty();
// If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times.
@ -242,7 +190,7 @@ impl FsResolver {
return_errno_with_message!(Errno::ELOOP, "too many symlinks");
}
let link_path_remain = {
let mut tmp_link_path = next_dentry.inode().raw_inode().read_link()?;
let mut tmp_link_path = next_dentry.vnode().inode().read_link()?;
if tmp_link_path.is_empty() {
return_errno_with_message!(Errno::ENOENT, "empty symlink");
}
@ -277,7 +225,7 @@ impl FsResolver {
}
/// Lookup dentry from the giving fd
fn lookup_dentry_from_fd(&self, fd: FileDescripter) -> Result<Arc<Dentry>> {
fn lookup_from_fd(&self, fd: FileDescripter) -> Result<Arc<Dentry>> {
let current = current!();
let file_table = current.file_table().lock();
let inode_handle = file_table
@ -286,6 +234,78 @@ impl FsResolver {
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?;
Ok(inode_handle.dentry().clone())
}
/// Lookup the dir dentry and base file name of the giving path.
///
/// If the last component is a symlink, do not deference it
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<Dentry>, String)> {
self.lookup_dir_and_base_name_inner(path, false)
}
fn lookup_dir_and_base_name_inner(
&self,
path: &FsPath,
follow_tail_link: bool,
) -> Result<(Arc<Dentry>, String)> {
let (mut dir_dentry, mut base_name) = match path.inner {
FsPathInner::Absolute(path) => {
let (dir, file_name) = split_path(path);
(
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?,
String::from(file_name),
)
}
FsPathInner::CwdRelative(path) => {
let (dir, file_name) = split_path(path);
(
self.lookup_from_parent(&self.cwd, path, true)?,
String::from(file_name),
)
}
FsPathInner::FdRelative(fd, path) => {
let (dir, file_name) = split_path(path);
let parent = self.lookup_from_fd(fd)?;
(
self.lookup_from_parent(&parent, path, true)?,
String::from(file_name),
)
}
_ => return_errno!(Errno::ENOENT),
};
if !follow_tail_link {
return Ok((dir_dentry, base_name));
}
// Dereference the tail symlinks if needed
loop {
match dir_dentry.lookup(&base_name.trim_end_matches('/')) {
Ok(dentry) if dentry.vnode().inode().metadata().type_ == InodeType::SymLink => {
let link = {
let mut link = dentry.vnode().inode().read_link()?;
if link.is_empty() {
return_errno_with_message!(Errno::ENOENT, "invalid symlink");
}
if base_name.ends_with("/") && !link.ends_with("/") {
link += "/";
}
link
};
let (dir, file_name) = split_path(&link);
if dir.starts_with("/") {
dir_dentry =
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?;
base_name = String::from(file_name);
} else {
dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?;
base_name = String::from(file_name);
}
}
_ => break,
}
}
Ok((dir_dentry, base_name))
}
}
pub const AT_FDCWD: FileDescripter = -100;

View File

@ -1,14 +1,6 @@
pub mod events;
pub mod fcntl;
pub mod file;
pub mod file_handle;
pub mod file_table;
pub mod fs_resolver;
pub mod inode_handle;
pub mod ioctl;
pub mod poll;
pub mod ramfs;
pub mod stat;
pub mod stdio;
pub mod utils;
pub mod vfs_inode;

View File

@ -7,9 +7,8 @@ use jinux_frame::vm::VmFrame;
use spin::{RwLock, RwLockWriteGuard};
use super::*;
use crate::fs::ioctl::IoctlCmd;
use crate::fs::utils::{
DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, Metadata, SuperBlock,
DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
};
pub struct RamFS {

View File

@ -1,8 +1,9 @@
use super::events::IoEvents;
use crate::prelude::*;
use crate::tty::{get_n_tty, Tty};
use super::file::{File, FileDescripter};
use super::file_handle::File;
use super::file_table::FileDescripter;
use super::utils::IoEvents;
pub const FD_STDIN: FileDescripter = 0;
pub const FD_STDOUT: FileDescripter = 1;
@ -37,7 +38,7 @@ impl File for Stdin {
}
}
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg)
} else {
@ -46,7 +47,7 @@ impl File for Stdin {
}
}
impl File for Stdout {
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg)
} else {
@ -64,7 +65,7 @@ impl File for Stdout {
}
impl File for Stderr {
fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result<i32> {
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg)
} else {

View File

@ -1,12 +1,11 @@
use crate::prelude::*;
use alloc::string::String;
use super::{InodeMode, InodeType, NAME_MAX};
use crate::fs::vfs_inode::VfsInode;
use super::{InodeMode, InodeType, Vnode, NAME_MAX};
pub struct Dentry {
inner: RwLock<Dentry_>,
inode: VfsInode,
vnode: Vnode,
}
struct Dentry_ {
@ -29,16 +28,16 @@ impl Dentry_ {
impl Dentry {
/// Create a new dentry cache with root inode
pub fn new_root(inode: VfsInode) -> Arc<Self> {
let root = Self::new("/", inode, None);
pub fn new_root(root_vnode: Vnode) -> Arc<Self> {
let root = Self::new("/", root_vnode, None);
root
}
/// Internal constructor
fn new(name: &str, inode: VfsInode, parent: Option<Weak<Dentry>>) -> Arc<Self> {
fn new(name: &str, vnode: Vnode, parent: Option<Weak<Dentry>>) -> Arc<Self> {
let dentry = {
let inner = RwLock::new(Dentry_::new(name, parent));
Arc::new(Self { inner, inode })
Arc::new(Self { inner, vnode })
};
dentry.inner.write().this = Arc::downgrade(&dentry);
dentry
@ -48,20 +47,6 @@ impl Dentry {
self.inner.read().name.clone()
}
pub fn inode(&self) -> &VfsInode {
&self.inode
}
pub fn create_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
let mut inner = self.inner.write();
let child = {
let inode = VfsInode::new(self.inode().raw_inode().mknod(name, type_, mode)?)?;
Dentry::new(name, inode, Some(inner.this.clone()))
};
inner.children.insert(String::from(name), child.clone());
Ok(child)
}
fn this(&self) -> Arc<Dentry> {
self.inner.read().this.upgrade().unwrap()
}
@ -74,8 +59,22 @@ impl Dentry {
.map(|p| p.upgrade().unwrap())
}
pub fn get(&self, name: &str) -> Result<Arc<Dentry>> {
if self.inode.raw_inode().metadata().type_ != InodeType::Dir {
pub fn vnode(&self) -> &Vnode {
&self.vnode
}
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
let mut inner = self.inner.write();
let child = {
let vnode = Vnode::new(self.vnode.inode().mknod(name, type_, mode)?)?;
Dentry::new(name, vnode, Some(inner.this.clone()))
};
inner.children.insert(String::from(name), child.clone());
Ok(child)
}
pub fn lookup(&self, name: &str) -> Result<Arc<Dentry>> {
if self.vnode.inode().metadata().type_ != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if name.len() > NAME_MAX {
@ -90,8 +89,8 @@ impl Dentry {
if let Some(dentry) = inner.children.get(name) {
dentry.clone()
} else {
let inode = VfsInode::new(self.inode.raw_inode().lookup(name)?)?;
let dentry = Dentry::new(name, inode, Some(inner.this.clone()));
let vnode = Vnode::new(self.vnode.inode().lookup(name)?)?;
let dentry = Dentry::new(name, vnode, Some(inner.this.clone()));
inner.children.insert(String::from(name), dentry.clone());
dentry
}

View File

@ -4,8 +4,7 @@ use bitflags::bitflags;
use core::any::Any;
use jinux_frame::vm::VmFrame;
use super::{DirentWriterContext, FileSystem};
use crate::fs::ioctl::IoctlCmd;
use super::{DirentWriterContext, FileSystem, IoctlCmd};
use crate::prelude::*;
#[repr(u32)]

View File

@ -4,19 +4,31 @@ pub use access_mode::AccessMode;
pub use creation_flags::CreationFlags;
pub use dentry_cache::Dentry;
pub use dirent_writer::{DirentWriter, DirentWriterContext};
pub use events::IoEvents;
pub use fcntl::FcntlCmd;
pub use fs::{FileSystem, SuperBlock};
pub use inode::{Inode, InodeMode, InodeType, Metadata, Timespec};
pub use ioctl::IoctlCmd;
pub use page_cache::PageCacheManager;
pub use poll::{c_nfds, c_pollfd, PollFd};
pub use stat::Stat;
pub use status_flags::StatusFlags;
pub use vnode::Vnode;
mod access_mode;
mod creation_flags;
mod dentry_cache;
mod dirent_writer;
mod events;
mod fcntl;
mod fs;
mod inode;
mod ioctl;
mod page_cache;
mod poll;
mod stat;
mod status_flags;
mod vnode;
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
pub enum SeekFrom {

View File

@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
use super::events::IoEvents;
use super::file::FileDescripter;
use super::IoEvents;
use crate::fs::file_table::FileDescripter;
pub type c_nfds = u64;
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h

View File

@ -0,0 +1,31 @@
use crate::prelude::*;
use super::{Inode, PageCacheManager};
use crate::rights::Rights;
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
/// VFS-level representation of an inode
#[derive(Clone)]
pub struct Vnode {
inode: Arc<dyn Inode>,
pages: Vmo,
}
impl Vnode {
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode)));
let pages = VmoOptions::<Rights>::new(inode.metadata().size)
.flags(VmoFlags::RESIZABLE)
.pager(page_cache_manager)
.alloc()?;
Ok(Self { inode, pages })
}
pub fn pages(&self) -> &Vmo {
&self.pages
}
pub fn inode(&self) -> &Arc<dyn Inode> {
&self.inode
}
}

View File

@ -1,30 +0,0 @@
use crate::prelude::*;
use super::utils::{Inode, PageCacheManager};
use crate::rights::Rights;
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
#[derive(Clone)]
pub struct VfsInode {
raw_inode: Arc<dyn Inode>,
pages: Vmo,
}
impl VfsInode {
pub fn new(raw_inode: Arc<dyn Inode>) -> Result<Self> {
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&raw_inode)));
let pages = VmoOptions::<Rights>::new(raw_inode.metadata().size)
.flags(VmoFlags::RESIZABLE)
.pager(page_cache_manager)
.alloc()?;
Ok(Self { raw_inode, pages })
}
pub fn pages(&self) -> &Vmo {
&self.pages
}
pub fn raw_inode(&self) -> &Arc<dyn Inode> {
&self.raw_inode
}
}

View File

@ -7,6 +7,7 @@ use jinux_frame::{
use crate::{
current_thread,
fs::file_table::FileTable,
fs::fs_resolver::FsResolver,
prelude::*,
process::{
posix_thread::{
@ -209,6 +210,8 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
// clone file table
let child_file_table = clone_files(current.file_table(), clone_flags);
// clone fs
let child_fs = clone_fs(current.fs(), clone_flags);
// clone sig dispositions
let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags);
// clone system V semaphore
@ -240,6 +243,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
child_root_vmar.clone(),
Weak::new(),
child_file_table,
child_fs,
child_sig_dispositions,
)
});
@ -337,11 +341,15 @@ fn clone_cpu_context(
child_context
}
fn clone_fs(clone_flags: CloneFlags) -> Result<()> {
fn clone_fs(
parent_fs: &Arc<RwLock<FsResolver>>,
clone_flags: CloneFlags,
) -> Arc<RwLock<FsResolver>> {
if clone_flags.contains(CloneFlags::CLONE_FS) {
warn!("CLONE_FS is not supported now")
parent_fs.clone()
} else {
Arc::new(RwLock::new(parent_fs.read().clone()))
}
Ok(())
}
fn clone_files(

View File

@ -11,6 +11,7 @@ use self::signal::sig_queues::SigQueues;
use self::signal::signals::kernel::KernelSignal;
use self::status::ProcessStatus;
use crate::fs::file_table::FileTable;
use crate::fs::fs_resolver::FsResolver;
use crate::prelude::*;
use crate::rights::Full;
use crate::thread::kernel_thread::KernelThreadExt;
@ -65,6 +66,8 @@ pub struct Process {
process_group: Mutex<Weak<ProcessGroup>>,
/// File table
file_table: Arc<Mutex<FileTable>>,
/// FsResolver
fs: Arc<RwLock<FsResolver>>,
/// resource limits
resource_limits: Mutex<ResourceLimits>,
@ -99,6 +102,7 @@ impl Process {
root_vmar: Arc<Vmar<Full>>,
process_group: Weak<ProcessGroup>,
file_table: Arc<Mutex<FileTable>>,
fs: Arc<RwLock<FsResolver>>,
sig_dispositions: Arc<Mutex<SigDispositions>>,
) -> Self {
let parent = if pid == 0 {
@ -125,6 +129,7 @@ impl Process {
children: Mutex::new(children),
process_group: Mutex::new(process_group),
file_table,
fs,
sig_dispositions,
sig_queues: Mutex::new(SigQueues::new()),
resource_limits: Mutex::new(resource_limits),
@ -191,6 +196,7 @@ impl Process {
let pid = thread.tid();
let user_vm = UserVm::new();
let file_table = FileTable::new_with_stdio();
let fs = FsResolver::new().unwrap();
let sig_dispositions = SigDispositions::new();
let process = Process::new(
@ -201,6 +207,7 @@ impl Process {
Arc::new(root_vmar),
Weak::new(),
Arc::new(Mutex::new(file_table)),
Arc::new(RwLock::new(fs)),
Arc::new(Mutex::new(sig_dispositions)),
);
process
@ -224,6 +231,7 @@ impl Process {
let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone());
let pid = thread.tid();
let file_table = FileTable::new();
let fs = FsResolver::new().unwrap();
let sig_dispositions = SigDispositions::new();
// FIXME: kernel process does not need root vmar
let root_vmar = Vmar::<Full>::new_root().unwrap();
@ -235,6 +243,7 @@ impl Process {
Arc::new(root_vmar),
Weak::new(),
Arc::new(Mutex::new(file_table)),
Arc::new(RwLock::new(fs)),
Arc::new(Mutex::new(sig_dispositions)),
)
});
@ -287,6 +296,10 @@ impl Process {
&self.file_table
}
pub fn fs(&self) -> &Arc<RwLock<FsResolver>> {
&self.fs
}
/// create a new process group for the process and add it to globle table.
/// Then set the process group for current process.
fn create_and_set_process_group(self: &Arc<Self>) {

View File

@ -1,7 +1,7 @@
use super::SyscallReturn;
use super::SYS_CLOSE;
use crate::log_syscall_entry;
use crate::{fs::file::FileDescripter, prelude::*};
use crate::{fs::file_table::FileDescripter, prelude::*};
pub fn sys_close(fd: FileDescripter) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_CLOSE);

View File

@ -1,7 +1,7 @@
use super::{SyscallReturn, SYS_FCNTL};
use crate::fs::fcntl::FcntlCmd;
use crate::fs::utils::FcntlCmd;
use crate::log_syscall_entry;
use crate::{fs::file::FileDescripter, prelude::*};
use crate::{fs::file_table::FileDescripter, prelude::*};
pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCNTL);

View File

@ -1,6 +1,6 @@
use jinux_frame::vm::VmIo;
use crate::fs::stat::Stat;
use crate::fs::utils::Stat;
use crate::{log_syscall_entry, prelude::*};
use crate::syscall::{SyscallReturn, SYS_FSTAT};

View File

@ -1,5 +1,5 @@
use crate::fs::file::FileDescripter;
use crate::fs::ioctl::IoctlCmd;
use crate::fs::file_table::FileDescripter;
use crate::fs::utils::IoctlCmd;
use crate::log_syscall_entry;
use crate::prelude::*;

View File

@ -1,5 +1,5 @@
use crate::log_syscall_entry;
use crate::{fs::file::FileDescripter, prelude::*};
use crate::{fs::file_table::FileDescripter, prelude::*};
use super::SyscallReturn;
use super::SYS_LSEEK;

View File

@ -1,4 +1,4 @@
use crate::fs::stat::Stat;
use crate::fs::utils::Stat;
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN;

View File

@ -1,6 +1,6 @@
//! This mod defines mmap flags and the handler to syscall mmap
use crate::fs::file::FileDescripter;
use crate::fs::file_table::FileDescripter;
use crate::process::process_vm::mmap_flags::MMapFlags;
use crate::rights::Rights;
use crate::vm::perms::VmPerms;

View File

@ -1,6 +1,8 @@
use crate::fs::file::File;
use crate::fs::file::FileDescripter;
use crate::fs::file_handle::FileHandle;
use crate::fs::{
file_handle::{File, FileHandle},
file_table::FileDescripter,
fs_resolver::{FsPath, AT_FDCWD},
};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN;
@ -10,12 +12,10 @@ use crate::util::read_cstring_from_user;
use super::SyscallReturn;
use super::SYS_OPENAT;
const AT_FDCWD: FileDescripter = -100;
pub fn sys_openat(
dirfd: FileDescripter,
pathname_addr: Vaddr,
flags: i32,
flags: u32,
mode: u16,
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_OPENAT);
@ -53,7 +53,18 @@ pub fn sys_openat(
let fd = file_table.insert(tty_file);
return Ok(SyscallReturn::Return(fd as _));
}
todo!()
// The common path
let current = current!();
let file_handle = {
let pathname = pathname.to_string_lossy();
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
let inode_handle = current.fs().read().open(&fs_path, flags, mode)?;
FileHandle::new_inode_handle(inode_handle)
};
let mut file_table = current.file_table().lock();
let fd = file_table.insert(file_handle);
Ok(SyscallReturn::Return(fd as _))
}
/// File for output busybox ash log.

View File

@ -1,9 +1,9 @@
use core::time::Duration;
use crate::fs::poll::{c_pollfd, PollFd};
use crate::fs::utils::{c_pollfd, PollFd};
use crate::log_syscall_entry;
use crate::util::{read_val_from_user, write_val_to_user};
use crate::{fs::poll::c_nfds, prelude::*};
use crate::{fs::utils::c_nfds, prelude::*};
use super::SyscallReturn;
use super::SYS_POLL;

View File

@ -1,6 +1,6 @@
use crate::log_syscall_entry;
use crate::util::write_bytes_to_user;
use crate::{fs::file::FileDescripter, prelude::*};
use crate::{fs::file_table::FileDescripter, prelude::*};
use super::SyscallReturn;
use super::SYS_READ;

View File

@ -1,4 +1,4 @@
use crate::fs::file::FileDescripter;
use crate::fs::file_table::FileDescripter;
use crate::{log_syscall_entry, prelude::*};
use crate::syscall::SYS_WRITE;

View File

@ -1,4 +1,4 @@
use crate::fs::events::IoEvents;
use crate::fs::utils::IoEvents;
use crate::process::signal::constants::{SIGINT, SIGQUIT};
use crate::{
prelude::*,

View File

@ -1,11 +1,12 @@
use self::line_discipline::LineDiscipline;
use crate::driver::tty::TtyDriver;
use crate::fs::events::IoEvents;
use crate::fs::ioctl::IoctlCmd;
use crate::fs::{
file_handle::File,
utils::{IoEvents, IoctlCmd},
};
use crate::prelude::*;
use crate::process::{process_table, Pgid};
use crate::util::{read_val_from_user, write_val_to_user};
use crate::{fs::file::File, prelude::*};
pub mod line_discipline;
pub mod termio;