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 crate::tty::get_n_tty;
use core::any::Any; use core::any::Any;
use super::events::IoEvents; use crate::fs::utils::{IoEvents, IoctlCmd};
use super::ioctl::IoctlCmd;
pub type FileDescripter = i32;
/// The basic operations defined on a file /// The basic operations defined on a file
pub trait File: Send + Sync + Any { pub trait File: Send + Sync + Any {

View File

@ -1,5 +1,4 @@
use crate::prelude::*; use crate::prelude::*;
use crate::rights::{Rights, TRights}; use crate::rights::{Rights, TRights};
use super::*; use super::*;
@ -10,7 +9,7 @@ impl InodeHandle<Rights> {
access_mode: AccessMode, access_mode: AccessMode,
status_flags: StatusFlags, status_flags: StatusFlags,
) -> Result<Self> { ) -> 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() { if access_mode.is_readable() && !inode_info.mode.is_readable() {
return_errno_with_message!(Errno::EACCES, "File is not 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 dyn_cap;
mod static_cap; mod static_cap;
use super::utils::{ use crate::fs::utils::{
AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags, AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags,
}; };
use crate::prelude::*; use crate::prelude::*;
@ -23,17 +23,17 @@ struct InodeHandle_ {
impl InodeHandle_ { impl InodeHandle_ {
pub fn read(&self, buf: &mut [u8]) -> Result<usize> { pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
let mut offset = self.offset.lock(); 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 start = file_size.min(*offset);
let end = file_size.min(*offset + buf.len()); let end = file_size.min(*offset + buf.len());
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
self.dentry self.dentry
.vnode()
.inode() .inode()
.raw_inode()
.read_at(start, &mut buf[0..end - start])? .read_at(start, &mut buf[0..end - start])?
} else { } else {
self.dentry self.dentry
.inode() .vnode()
.pages() .pages()
.read_bytes(start, &mut buf[0..end - start])?; .read_bytes(start, &mut buf[0..end - start])?;
end - start end - start
@ -45,24 +45,21 @@ impl InodeHandle_ {
pub fn write(&self, buf: &[u8]) -> Result<usize> { pub fn write(&self, buf: &[u8]) -> Result<usize> {
let mut offset = self.offset.lock(); 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) { if self.status_flags.lock().contains(StatusFlags::O_APPEND) {
*offset = file_size; *offset = file_size;
} }
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { 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 { } else {
let pages = self.dentry.inode().pages(); let pages = self.dentry.vnode().pages();
let should_expand_size = *offset + buf.len() > file_size; let should_expand_size = *offset + buf.len() > file_size;
if should_expand_size { if should_expand_size {
pages.resize(*offset + buf.len())?; pages.resize(*offset + buf.len())?;
} }
pages.write_bytes(*offset, buf)?; pages.write_bytes(*offset, buf)?;
if should_expand_size { if should_expand_size {
self.dentry self.dentry.vnode().inode().resize(*offset + buf.len())?;
.inode()
.raw_inode()
.resize(*offset + buf.len())?;
} }
buf.len() buf.len()
}; };
@ -81,7 +78,7 @@ impl InodeHandle_ {
off as i64 off as i64
} }
SeekFrom::End(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); assert!(file_size >= 0);
file_size file_size
.checked_add(off) .checked_add(off)
@ -128,11 +125,7 @@ impl InodeHandle_ {
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> { pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
let mut offset = self.offset.lock(); let mut offset = self.offset.lock();
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer); let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
let written_size = self let written_size = self.dentry.vnode().inode().readdir(&mut dir_writer_ctx)?;
.dentry
.inode()
.raw_inode()
.readdir(&mut dir_writer_ctx)?;
*offset = dir_writer_ctx.pos(); *offset = dir_writer_ctx.pos();
Ok(written_size) Ok(written_size)
} }

View File

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

View File

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

View File

@ -2,14 +2,13 @@ use crate::prelude::*;
use alloc::str; use alloc::str;
use alloc::string::String; use alloc::string::String;
use super::file::FileDescripter; use super::file_handle::InodeHandle;
use super::inode_handle::InodeHandle; use super::file_table::FileDescripter;
use super::ramfs::RamFS; use super::ramfs::RamFS;
use super::utils::{ use super::utils::{
AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, PATH_MAX, AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, Vnode,
SYMLINKS_MAX, PATH_MAX, SYMLINKS_MAX,
}; };
use super::vfs_inode::VfsInode;
lazy_static! { lazy_static! {
static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new(); static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new();
@ -32,8 +31,8 @@ impl Clone for FsResolver {
impl FsResolver { impl FsResolver {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let root = { let root = {
let root_inode = VfsInode::new(ROOT_FS.root_inode())?; let root_vnode = Vnode::new(ROOT_FS.root_inode())?;
Dentry::new_root(root_inode) Dentry::new_root(root_vnode)
}; };
Ok(Self { Ok(Self {
root: root.clone(), root: root.clone(),
@ -64,9 +63,9 @@ impl FsResolver {
let inode_mode = InodeMode::from_bits_truncate(mode); let inode_mode = InodeMode::from_bits_truncate(mode);
let follow_tail_link = !creation_flags.contains(CreationFlags::O_NOFOLLOW); 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) => { Ok(dentry) => {
let inode = dentry.inode().raw_inode(); let inode = dentry.vnode().inode();
if inode.metadata().type_ == InodeType::SymLink if inode.metadata().type_ == InodeType::SymLink
&& !status_flags.contains(StatusFlags::O_PATH) && !status_flags.contains(StatusFlags::O_PATH)
{ {
@ -94,15 +93,15 @@ impl FsResolver {
if creation_flags.contains(CreationFlags::O_DIRECTORY) { if creation_flags.contains(CreationFlags::O_DIRECTORY) {
return_errno_with_message!(Errno::ENOTDIR, "cannot create 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("/") { if file_name.ends_with("/") {
return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); 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"); return_errno_with_message!(Errno::EPERM, "file cannot be created");
} }
let new_dentry = let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?;
dir_dentry.create_child(&file_name, InodeType::File, inode_mode)?;
new_dentry new_dentry
} }
Err(e) => return Err(e), Err(e) => return Err(e),
@ -112,8 +111,17 @@ impl FsResolver {
Ok(inode_handle) Ok(inode_handle)
} }
/// Lookup dentry according to FsPath /// Lookup dentry according to FsPath, always follow symlinks
pub fn lookup(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> { 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 { let dentry = match path.inner {
FsPathInner::Absolute(path) => { FsPathInner::Absolute(path) => {
self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)? 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::Cwd => self.cwd.clone(),
FsPathInner::FdRelative(fd, path) => { 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)? 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) 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 /// Lookup dentry from parent
/// ///
/// The length of `path` cannot exceed PATH_MAX. /// The length of `path` cannot exceed PATH_MAX.
@ -232,8 +180,8 @@ impl FsResolver {
}; };
// Iterate next dentry // Iterate next dentry
let next_dentry = dentry.get(next_name)?; let next_dentry = dentry.lookup(next_name)?;
let next_type = next_dentry.inode().raw_inode().metadata().type_; let next_type = next_dentry.vnode().inode().metadata().type_;
let next_is_tail = path_remain.is_empty(); let next_is_tail = path_remain.is_empty();
// If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. // 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"); return_errno_with_message!(Errno::ELOOP, "too many symlinks");
} }
let link_path_remain = { 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() { if tmp_link_path.is_empty() {
return_errno_with_message!(Errno::ENOENT, "empty symlink"); return_errno_with_message!(Errno::ENOENT, "empty symlink");
} }
@ -277,7 +225,7 @@ impl FsResolver {
} }
/// Lookup dentry from the giving fd /// 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 current = current!();
let file_table = current.file_table().lock(); let file_table = current.file_table().lock();
let inode_handle = file_table let inode_handle = file_table
@ -286,6 +234,78 @@ impl FsResolver {
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?; .ok_or(Error::with_message(Errno::EBADE, "not inode"))?;
Ok(inode_handle.dentry().clone()) 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; 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_handle;
pub mod file_table; pub mod file_table;
pub mod fs_resolver; pub mod fs_resolver;
pub mod inode_handle;
pub mod ioctl;
pub mod poll;
pub mod ramfs; pub mod ramfs;
pub mod stat;
pub mod stdio; pub mod stdio;
pub mod utils; pub mod utils;
pub mod vfs_inode;

View File

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

View File

@ -1,8 +1,9 @@
use super::events::IoEvents;
use crate::prelude::*; use crate::prelude::*;
use crate::tty::{get_n_tty, Tty}; 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_STDIN: FileDescripter = 0;
pub const FD_STDOUT: FileDescripter = 1; 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() { if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg) console.ioctl(cmd, arg)
} else { } else {
@ -46,7 +47,7 @@ impl File for Stdin {
} }
} }
impl File for Stdout { 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() { if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg) console.ioctl(cmd, arg)
} else { } else {
@ -64,7 +65,7 @@ impl File for Stdout {
} }
impl File for Stderr { 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() { if let Some(console) = self.console.as_ref() {
console.ioctl(cmd, arg) console.ioctl(cmd, arg)
} else { } else {

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
use super::events::IoEvents; use super::IoEvents;
use super::file::FileDescripter; use crate::fs::file_table::FileDescripter;
pub type c_nfds = u64; pub type c_nfds = u64;
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h // 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::{ use crate::{
current_thread, current_thread,
fs::file_table::FileTable, fs::file_table::FileTable,
fs::fs_resolver::FsResolver,
prelude::*, prelude::*,
process::{ process::{
posix_thread::{ posix_thread::{
@ -209,6 +210,8 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
// clone file table // clone file table
let child_file_table = clone_files(current.file_table(), clone_flags); 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 // clone sig dispositions
let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags); let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags);
// clone system V semaphore // clone system V semaphore
@ -240,6 +243,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
child_root_vmar.clone(), child_root_vmar.clone(),
Weak::new(), Weak::new(),
child_file_table, child_file_table,
child_fs,
child_sig_dispositions, child_sig_dispositions,
) )
}); });
@ -337,11 +341,15 @@ fn clone_cpu_context(
child_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) { 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( fn clone_files(

View File

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

View File

@ -1,7 +1,7 @@
use super::SyscallReturn; use super::SyscallReturn;
use super::SYS_CLOSE; use super::SYS_CLOSE;
use crate::log_syscall_entry; 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> { pub fn sys_close(fd: FileDescripter) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_CLOSE); log_syscall_entry!(SYS_CLOSE);

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
use crate::log_syscall_entry; use crate::log_syscall_entry;
use crate::{fs::file::FileDescripter, prelude::*}; use crate::{fs::file_table::FileDescripter, prelude::*};
use super::SyscallReturn; use super::SyscallReturn;
use super::SYS_LSEEK; 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::log_syscall_entry;
use crate::prelude::*; use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN; use crate::syscall::constants::MAX_FILENAME_LEN;

View File

@ -1,6 +1,6 @@
//! This mod defines mmap flags and the handler to syscall mmap //! 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::process::process_vm::mmap_flags::MMapFlags;
use crate::rights::Rights; use crate::rights::Rights;
use crate::vm::perms::VmPerms; use crate::vm::perms::VmPerms;

View File

@ -1,6 +1,8 @@
use crate::fs::file::File; use crate::fs::{
use crate::fs::file::FileDescripter; file_handle::{File, FileHandle},
use crate::fs::file_handle::FileHandle; file_table::FileDescripter,
fs_resolver::{FsPath, AT_FDCWD},
};
use crate::log_syscall_entry; use crate::log_syscall_entry;
use crate::prelude::*; use crate::prelude::*;
use crate::syscall::constants::MAX_FILENAME_LEN; use crate::syscall::constants::MAX_FILENAME_LEN;
@ -10,12 +12,10 @@ use crate::util::read_cstring_from_user;
use super::SyscallReturn; use super::SyscallReturn;
use super::SYS_OPENAT; use super::SYS_OPENAT;
const AT_FDCWD: FileDescripter = -100;
pub fn sys_openat( pub fn sys_openat(
dirfd: FileDescripter, dirfd: FileDescripter,
pathname_addr: Vaddr, pathname_addr: Vaddr,
flags: i32, flags: u32,
mode: u16, mode: u16,
) -> Result<SyscallReturn> { ) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_OPENAT); log_syscall_entry!(SYS_OPENAT);
@ -53,7 +53,18 @@ pub fn sys_openat(
let fd = file_table.insert(tty_file); let fd = file_table.insert(tty_file);
return Ok(SyscallReturn::Return(fd as _)); 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. /// File for output busybox ash log.

View File

@ -1,9 +1,9 @@
use core::time::Duration; 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::log_syscall_entry;
use crate::util::{read_val_from_user, write_val_to_user}; 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::SyscallReturn;
use super::SYS_POLL; use super::SYS_POLL;

View File

@ -1,6 +1,6 @@
use crate::log_syscall_entry; use crate::log_syscall_entry;
use crate::util::write_bytes_to_user; 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::SyscallReturn;
use super::SYS_READ; 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::{log_syscall_entry, prelude::*};
use crate::syscall::SYS_WRITE; 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::process::signal::constants::{SIGINT, SIGQUIT};
use crate::{ use crate::{
prelude::*, prelude::*,

View File

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