Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jeehoonkang committed Aug 18, 2021
1 parent 3879b87 commit e2a357c
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 161 deletions.
12 changes: 6 additions & 6 deletions kernel-rs/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use core::{
use crate::{
arch::addr::UVAddr,
arena::{Arena, ArenaObject, ArenaRc, ArrayArena},
fs::{FileSystem, FileSystemExt, InodeGuard, RcInode, Ufs},
fs::{FileSystem, FileSystemExt, InodeGuard, InodeInner, RcInode, Ufs},
hal::hal,
param::{BSIZE, MAXOPBLOCKS, NFILE},
pipe::AllocatedPipe,
Expand Down Expand Up @@ -47,7 +47,7 @@ pub struct InodeFileType {
/// It can be acquired when the inode of `InodeFileType` is locked. `ip` is the guard of the locked
/// inode. `off` is a mutable reference to the offset. Accessing `off` is guaranteed to be safe
/// since the inode is locked.
struct InodeFileTypeGuard<'a, I> {
struct InodeFileTypeGuard<'a, I: InodeInner> {
ip: ManuallyDrop<InodeGuard<'a, I>>,
off: &'a mut u32,
}
Expand Down Expand Up @@ -91,29 +91,29 @@ impl InodeFileType {
}
}

impl<I> InodeFileTypeGuard<'_, I> {
impl<I: InodeInner> InodeFileTypeGuard<'_, I> {
fn free(mut self, ctx: &KernelCtx<'_, '_>) {
let ip = unsafe { ManuallyDrop::take(&mut self.ip) };
ip.free(ctx);
core::mem::forget(self);
}
}

impl<'a, I> Deref for InodeFileTypeGuard<'a, I> {
impl<'a, I: InodeInner> Deref for InodeFileTypeGuard<'a, I> {
type Target = InodeGuard<'a, I>;

fn deref(&self) -> &Self::Target {
&self.ip
}
}

impl<'a, I> DerefMut for InodeFileTypeGuard<'a, I> {
impl<'a, I: InodeInner> DerefMut for InodeFileTypeGuard<'a, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ip
}
}

impl<I> Drop for InodeFileTypeGuard<'_, I> {
impl<I: InodeInner> Drop for InodeFileTypeGuard<'_, I> {
fn drop(&mut self) {
// HACK(@efenniht): we really need linear type here:
// https://github.com/rust-lang/rfcs/issues/814
Expand Down
27 changes: 24 additions & 3 deletions kernel-rs/src/fs/lfs/inode.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
use core::ops::Deref;

use super::super::{InodeGuard, InodeInner};
use super::Inode;
use crate::arena::ArenaObject;
use crate::{arena::ArenaObject, proc::KernelCtx};

pub struct I {}

pub struct InodeInner {}
impl InodeInner for I {
#[inline]
fn read_internal<
'id,
's,
K: Deref<Target = KernelCtx<'id, 's>>,
F: FnMut(u32, &[u8], &mut K) -> Result<(), ()>,
>(
guard: &mut InodeGuard<'_, Self>,
off: u32,
n: u32,
f: F,
k: K,
) -> Result<usize, ()> {
todo!()
}
}

impl ArenaObject for Inode<InodeInner> {
impl ArenaObject for Inode<I> {
type Ctx<'a, 'id: 'a> = ();

#[allow(clippy::needless_lifetimes)]
Expand Down
4 changes: 2 additions & 2 deletions kernel-rs/src/fs/lfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{proc::KernelCtx, util::strong_pin::StrongPin};
mod inode;
mod superblock;

pub use inode::InodeInner;
pub use inode::I;
pub use superblock::Superblock;

pub struct Lfs {
Expand All @@ -37,7 +37,7 @@ impl Lfs {

impl FileSystem for Lfs {
type Dirent = ();
type InodeInner = InodeInner;
type InodeInner = I;

fn init(&self, dev: u32, ctx: &KernelCtx<'_, '_>) {
todo!()
Expand Down
108 changes: 96 additions & 12 deletions kernel-rs/src/fs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use core::mem;
use core::ops::Deref;

use bitflags::bitflags;
use zerocopy::{AsBytes, FromBytes};

use crate::{
arch::addr::UVAddr,
arena::{ArenaObject, ArenaRc, ArrayArena},
lock::SleepLock,
param::NINODE,
Expand Down Expand Up @@ -51,19 +54,19 @@ pub enum InodeType {
// Instead, every method that needs to be inside a transaction explicitly
// takes a FsTransaction value as an argument.
// https://github.com/kaist-cp/rv6/issues/328
pub struct InodeGuard<'a, I> {
pub struct InodeGuard<'a, I: InodeInner> {
pub inode: &'a Inode<I>,
}

impl<I> Deref for InodeGuard<'_, I> {
impl<I: InodeInner> Deref for InodeGuard<'_, I> {
type Target = Inode<I>;

fn deref(&self) -> &Self::Target {
self.inode
}
}

impl<I> InodeGuard<'_, I> {
impl<I: InodeInner> InodeGuard<'_, I> {
pub fn deref_inner(&self) -> &I {
// SAFETY: self.inner is locked.
unsafe { &*self.inner.get_mut_raw() }
Expand All @@ -79,10 +82,71 @@ impl<I> InodeGuard<'_, I> {
unsafe { self.inner.unlock(ctx) };
core::mem::forget(self);
}

/// Copy data into `dst` from the content of inode at offset `off`.
/// Return Ok(()) on success, Err(()) on failure.
pub fn read_kernel<T: AsBytes + FromBytes>(
&mut self,
dst: &mut T,
off: u32,
ctx: &KernelCtx<'_, '_>,
) -> Result<(), ()> {
let bytes = self.read_bytes_kernel(dst.as_bytes_mut(), off, ctx);
if bytes == mem::size_of::<T>() {
Ok(())
} else {
Err(())
}
}

/// Copy data into `dst` from the content of inode at offset `off`.
/// Return the number of bytes copied.
pub fn read_bytes_kernel(
&mut self,
dst: &mut [u8],
off: u32,
ctx: &KernelCtx<'_, '_>,
) -> usize {
I::read_internal(
self,
off,
dst.len() as u32,
|off, src, _| {
dst[off as usize..off as usize + src.len()].clone_from_slice(src);
Ok(())
},
ctx,
)
.expect("read: should never fail")
}

/// Copy data into virtual address `dst` of the current process by `n` bytes
/// from the content of inode at offset `off`.
/// Returns Ok(number of bytes copied) on success, Err(()) on failure due to
/// accessing an invalid virtual address.
pub fn read_user(
&mut self,
dst: UVAddr,
off: u32,
n: u32,
ctx: &mut KernelCtx<'_, '_>,
) -> Result<usize, ()> {
I::read_internal(
self,
off,
n,
|off, src, ctx| {
ctx.proc_mut()
.memory_mut()
.copy_out_bytes(dst + off as usize, src)
},
ctx,
)
}
}

/// Unlock and put the given inode.
impl<I> Drop for InodeGuard<'_, I> {
impl<I: InodeInner> Drop for InodeGuard<'_, I> {
fn drop(&mut self) {
// HACK(@efenniht): we really need linear type here:
// https://github.com/rust-lang/rfcs/issues/814
Expand All @@ -91,7 +155,7 @@ impl<I> Drop for InodeGuard<'_, I> {
}

/// in-memory copy of an inode
pub struct Inode<I> {
pub struct Inode<I: InodeInner> {
/// Device number
pub dev: u32,

Expand All @@ -108,15 +172,13 @@ pub type RcInode<I> = ArenaRc<Itable<I>>;

pub struct Tx<'s, FS: FileSystem>
where
FS::InodeInner: 'static + Unpin,
Inode<FS::InodeInner>: ArenaObject,
{
fs: &'s FS,
}

impl<FS: FileSystem> Drop for Tx<'_, FS>
where
FS::InodeInner: 'static + Unpin,
Inode<FS::InodeInner>: ArenaObject,
{
fn drop(&mut self) {
Expand All @@ -128,7 +190,6 @@ where

impl<FS: FileSystem> Tx<'_, FS>
where
FS::InodeInner: 'static + Unpin,
Inode<FS::InodeInner>: ArenaObject,
{
/// Called at the end of each FS system call.
Expand All @@ -141,13 +202,38 @@ where
}
}

pub trait InodeInner: 'static + Unpin + Send + Sized {
/// Read data from inode.
///
/// `f` takes an offset and a slice as arguments. `f(off, src, ctx)` should copy
/// the content of `src` to the interval beginning at `off`th byte of the
/// destination, which the caller of this method knows.
// This method takes a function as an argument, because writing to kernel
// memory and user memory are very different from each other. Writing to a
// consecutive region in kernel memory can be done at once by simple memcpy.
// However, writing to user memory needs page table accesses since a single
// consecutive region in user memory may split into several pages in
// physical memory.
fn read_internal<
'id,
's,
K: Deref<Target = KernelCtx<'id, 's>>,
F: FnMut(u32, &[u8], &mut K) -> Result<(), ()>,
>(
guard: &mut InodeGuard<'_, Self>,
off: u32,
n: u32,
f: F,
k: K,
) -> Result<usize, ()>;
}

pub trait FileSystem: Sized
where
Self::InodeInner: 'static + Unpin,
Inode<Self::InodeInner>: ArenaObject,
{
type Dirent;
type InodeInner: Send;
type InodeInner: InodeInner;

/// Initializes the file system (loading from the disk).
fn init(&self, dev: u32, ctx: &KernelCtx<'_, '_>);
Expand Down Expand Up @@ -232,7 +318,6 @@ where

pub trait FileSystemExt: FileSystem
where
Self::InodeInner: 'static + Unpin,
Inode<Self::InodeInner>: ArenaObject,
{
/// Begins a transaction.
Expand All @@ -241,7 +326,6 @@ where

impl<FS: FileSystem> FileSystemExt for FS
where
FS::InodeInner: 'static + Unpin,
Inode<FS::InodeInner>: ArenaObject,
{
fn begin_tx(&self, ctx: &KernelCtx<'_, '_>) -> Tx<'_, Self> {
Expand Down
Loading

0 comments on commit e2a357c

Please sign in to comment.