Skip to content

Commit

Permalink
fix: compilation (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
llenotre committed Feb 16, 2025
1 parent e681cd4 commit 8aef847
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 261 deletions.
132 changes: 64 additions & 68 deletions kernel/src/file/fs/ext2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ use crate::{
device::DeviceIO,
file::{
fs::{
downcast_fs, ext2::dirent::Dirent, FileOps, FilesystemOps, FilesystemType, NodeOps,
StatSet, Statfs,
downcast_fs, ext2::dirent::Dirent, FileOps, Filesystem, FilesystemOps, FilesystemType,
NodeOps, StatSet, Statfs,
},
vfs,
vfs::node::Node,
Expand Down Expand Up @@ -307,6 +307,58 @@ impl NodeOps for Ext2NodeOps {
Ok(())
}

fn iter_entries(&self, dir: &Node, ctx: &mut DirContext) -> EResult<()> {
let fs = downcast_fs::<Ext2Fs>(&*dir.fs.ops);
let superblock = fs.superblock.lock();
let inode = Ext2INode::read(dir.inode as _, &superblock, &*fs.io)?;
if inode.get_type() != FileType::Directory {
return Err(errno!(ENOTDIR));
}
// Iterate on entries
let blk_size = superblock.get_block_size();
let mut buf = vec![0; blk_size as _]?;
'outer: while ctx.off < inode.get_size(&superblock) {
// Read content block
let blk_off = ctx.off / blk_size as u64;
let res = inode.translate_blk_off(blk_off as _, &superblock, &*fs.io);
let blk_off = match res {
Ok(Some(o)) => o,
// If reaching a zero block, stop
Ok(None) => break,
// If reaching the block limit, stop
Err(e) if e.as_int() == errno::EOVERFLOW => break,
Err(e) => return Err(e),
};
read_block(blk_off.get() as _, blk_size, &*fs.io, &mut buf)?;
// Read the next entry in the current block, skipping free ones
let ent = loop {
// Read entry
let inner_off = (ctx.off % blk_size as u64) as usize;
let ent = Dirent::from_slice(&mut buf[inner_off..], &superblock)?;
// Update offset
let prev_off = ctx.off;
ctx.off += ent.rec_len as u64;
// If not free, use this entry
if !ent.is_free() {
break ent;
}
// If the next entry is on another block, read next block
if (prev_off / blk_size as u64) != (ctx.off / blk_size as u64) {
continue 'outer;
}
};
let ent = DirEntry {
inode: ent.inode as _,
entry_type: ent.get_type(&superblock, &*fs.io)?,
name: ent.get_name(&superblock),
};
if !(ctx.write)(&ent)? {
break;
}
}
Ok(())
}

fn link(&self, parent: &Node, name: &[u8], target: INode) -> EResult<()> {
let fs = downcast_fs::<Ext2Fs>(&*parent.fs.ops);
if unlikely(fs.readonly) {
Expand Down Expand Up @@ -451,59 +503,6 @@ impl FileOps for Ext2FileOps {
superblock.write(&*fs.io)?;
Ok(())
}

fn iter_entries(&self, dir: &File, ctx: &mut DirContext) -> EResult<()> {
let node = dir.node().unwrap();
let fs = downcast_fs::<Ext2Fs>(&*node.fs.ops);
let superblock = fs.superblock.lock();
let inode = Ext2INode::read(node.inode as _, &superblock, &*fs.io)?;
if inode.get_type() != FileType::Directory {
return Err(errno!(ENOTDIR));
}
// Iterate on entries
let blk_size = superblock.get_block_size();
let mut buf = vec![0; blk_size as _]?;
'outer: while ctx.off < inode.get_size(&superblock) {
// Read content block
let blk_off = ctx.off / blk_size as u64;
let res = inode.translate_blk_off(blk_off as _, &superblock, &*fs.io);
let blk_off = match res {
Ok(Some(o)) => o,
// If reaching a zero block, stop
Ok(None) => break,
// If reaching the block limit, stop
Err(e) if e.as_int() == errno::EOVERFLOW => break,
Err(e) => return Err(e),
};
read_block(blk_off.get() as _, blk_size, &*fs.io, &mut buf)?;
// Read the next entry in the current block, skipping free ones
let ent = loop {
// Read entry
let inner_off = (ctx.off % blk_size as u64) as usize;
let ent = Dirent::from_slice(&mut buf[inner_off..], &superblock)?;
// Update offset
let prev_off = ctx.off;
ctx.off += ent.rec_len as u64;
// If not free, use this entry
if !ent.is_free() {
break ent;
}
// If the next entry is on another block, read next block
if (prev_off / blk_size as u64) != (ctx.off / blk_size as u64) {
continue 'outer;
}
};
let ent = DirEntry {
inode: ent.inode as _,
entry_type: ent.get_type(&superblock, &*fs.io)?,
name: ent.get_name(&superblock),
};
if !(ctx.write)(&ent)? {
break;
}
}
Ok(())
}
}

/// The ext2 superblock structure.
Expand Down Expand Up @@ -1009,20 +1008,16 @@ impl FilesystemOps for Ext2Fs {
})
}

fn root(&self) -> EResult<Arc<Node>> {
let superblock = self.superblock.lock();
// Check the inode exists
Ext2INode::read(inode::ROOT_DIRECTORY_INODE as _, &superblock, &*self.io)?;
Ok(Arc::new(Node {
inode: 0,
fs: self,
node_ops: Box::new(Ext2NodeOps)?,
file_ops: Box::new(Ext2FileOps)?,
pages: Default::default(),
})?)
fn root(&self, fs: Arc<Filesystem>) -> EResult<Arc<Node>> {
Filesystem::node_get_or_insert(fs, inode::ROOT_DIRECTORY_INODE as _, || {
let superblock = self.superblock.lock();
// Check the inode exists
Ext2INode::read(inode::ROOT_DIRECTORY_INODE as _, &superblock, &*self.io)?;
Ok((Box::new(Ext2NodeOps)?, Box::new(Ext2FileOps)?))
})
}

fn create_node(&self, stat: &Stat) -> EResult<Arc<Node>> {
fn create_node(&self, fs: Arc<Filesystem>, stat: &Stat) -> EResult<Arc<Node>> {
if unlikely(self.readonly) {
return Err(errno!(EROFS));
}
Expand Down Expand Up @@ -1061,11 +1056,12 @@ impl FilesystemOps for Ext2Fs {
superblock.write(&*self.io)?;
let node = Arc::new(Node {
inode: inode_index as _,
fs: self,
fs,
node_ops: Box::new(Ext2NodeOps)?,
file_ops: Box::new(Ext2FileOps)?,
pages: Default::default(),
})?;
node.fs.node_insert(node.clone())?;
Ok(node)
}

Expand Down
83 changes: 46 additions & 37 deletions kernel/src/file/fs/kernfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
//! This module implements utilities for kernfs.
use crate::file::{
fs::{FileOps, NodeOps},
fs::{DummyOps, FileOps, NodeOps},
vfs,
vfs::node::Node,
DirContext, DirEntry, File, FileType, INode, Stat,
DirContext, DirEntry, FileType, INode, Stat,
};
use core::{
cmp::min,
Expand Down Expand Up @@ -178,48 +178,48 @@ macro_rules! format_content {
#[derive(Debug, Default)]
pub struct StaticLink(pub &'static [u8]);

impl FileOps for StaticLink {
fn get_stat(&self, _file: &File) -> EResult<Stat> {
impl NodeOps for StaticLink {
fn get_stat(&self, _node: &Node) -> EResult<Stat> {
Ok(Stat {
mode: FileType::Link.to_mode() | 0o777,
..Default::default()
})
}

fn read(&self, _file: &File, off: u64, buf: &mut [u8]) -> EResult<usize> {
format_content!(off, buf, "{}", DisplayableStr(self.0))
fn readlink(&self, _node: &Node, buf: &mut [u8]) -> EResult<usize> {
format_content!(0, buf, "{}", DisplayableStr(self.0))
}
}

/// A builder for an entry of a [`StaticDir`].
/// Either [`NodeOps`] or [`FileOps`] initializer.
#[derive(Debug)]
pub enum EitherOps<T> {
/// Init [`NodeOps`]
Node(fn(T) -> AllocResult<Box<dyn NodeOps>>),
/// Init [`FileOps`]
File(fn(T) -> AllocResult<Box<dyn FileOps>>),
}

/// An entry of a [`StaticDir`].
///
/// `T` is the type of the parameter passed to `init`.
#[derive(Debug)]
pub struct StaticEntryBuilder<T = ()> {
/// The name of the entry.
pub struct StaticEntry<T = ()> {
/// The name of the entry
pub name: &'static [u8],
/// The type of the entry.
/// The type of the entry
pub entry_type: FileType,
/// A builder which returns a handle to perform operations on the node.
pub init: fn(T) -> AllocResult<Box<dyn FileOps>>,
}

/// Helper to initialize an entry handle, using [`Default`].
pub fn entry_init_default<'e, E: 'e + FileOps + Default>(
_: (),
) -> AllocResult<Box<dyn 'e + FileOps>> {
box_wrap(E::default())
/// A builder which returns a handle to perform operations
pub init: EitherOps<T>,
}

/// Helper to initialize an entry handle, using [`From`].
pub fn entry_init_from<'e, E: 'e + FileOps + From<T>, T>(
val: T,
) -> AllocResult<Box<dyn 'e + FileOps>> {
box_wrap(E::from(val))
/// Helper to wrap a [`FileOps`] into a [`Box`].
pub fn box_file<'n, N: 'n + FileOps>(ops: N) -> AllocResult<Box<dyn 'n + FileOps>> {
Ok(Box::new(ops)? as _)
}

/// Helper to wrap a [`FileOps`] into a [`Box`].
pub fn box_wrap<'n, N: 'n + FileOps>(ops: N) -> AllocResult<Box<dyn 'n + FileOps>> {
/// Helper to wrap a [`NodeOps`] into a [`Box`].
pub fn box_node<'n, N: 'n + NodeOps>(ops: N) -> AllocResult<Box<dyn 'n + NodeOps>> {
Ok(Box::new(ops)? as _)
}

Expand All @@ -232,24 +232,35 @@ pub struct StaticDir<T: 'static + Clone + Debug = ()> {
///
/// **Warning**: If this array is not sorted correctly, the behaviour of
/// [`NodeOps::lookup_entry`] is undefined.
pub entries: &'static [StaticEntryBuilder<T>],
pub entries: &'static [StaticEntry<T>],
/// Data used to initialize sub-nodes.
pub data: T,
}

impl<T: 'static + Clone + Debug> StaticDir<T> {
pub fn lookup_entry_inner(&self, ent: &mut vfs::Entry) -> EResult<()> {
pub fn lookup_entry_inner(&self, dir: &Node, ent: &mut vfs::Entry) -> EResult<()> {
ent.node = self
.entries
.binary_search_by(|e| e.name.cmp(&ent.name))
.ok()
.map(|index| {
let e = &self.entries[index];
let (node_ops, file_ops) = match self.entries[index].init {
EitherOps::Node(init) => {
let node_ops = init(self.data.clone())?;
let file_ops = Box::new(DummyOps)? as _;
(node_ops, file_ops)
}
EitherOps::File(init) => {
let node_ops = Box::new(DummyOps)? as _;
let file_ops = init(self.data.clone())?;
(node_ops, file_ops)
}
};
Arc::new(Node {
inode: 0,
fs: self,
node_ops: (),
file_ops: (e.init)(self.data.clone())?,
fs: dir.fs.clone(),
node_ops,
file_ops,
pages: Default::default(),
})
})
Expand All @@ -266,13 +277,11 @@ impl<T: 'static + Clone + Debug> NodeOps for StaticDir<T> {
})
}

fn lookup_entry(&self, _dir: &Node, ent: &mut vfs::Entry) -> EResult<()> {
self.lookup_entry_inner(ent)
fn lookup_entry(&self, dir: &Node, ent: &mut vfs::Entry) -> EResult<()> {
self.lookup_entry_inner(dir, ent)
}
}

impl<T: 'static + Clone + Debug> FileOps for StaticDir<T> {
fn iter_entries(&self, _dir: &File, ctx: &mut DirContext) -> EResult<()> {
fn iter_entries(&self, _dir: &Node, ctx: &mut DirContext) -> EResult<()> {
let iter = self.entries.iter().skip(ctx.off as usize);
for e in iter {
let ent = DirEntry {
Expand Down
Loading

0 comments on commit 8aef847

Please sign in to comment.