Skip to content

Commit

Permalink
optimize vfs getdents
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Mar 23, 2024
1 parent f044362 commit c2ae46c
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 222 deletions.
4 changes: 0 additions & 4 deletions crates/vfscore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,6 @@ pub trait INodeInterface: DowncastSync + Send + Sync {
Err(VfsError::NotSupported)
}

fn getdents(&self, _buffer: &mut [u8]) -> VfsResult<usize> {
Err(VfsError::NotSupported)
}

fn utimes(&self, _times: &mut [TimeSpec]) -> VfsResult<()> {
Err(VfsError::NotSupported)
}
Expand Down
10 changes: 4 additions & 6 deletions kernel/src/syscall/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,14 @@ impl UserTaskContainer {
OpenFlags::empty(),
)
.map_err(from_vfs)?;

let old_file_type = old_file.metadata().map_err(from_vfs)?.file_type;
let new_dir = to_node(&self.task, newdir_fd)?;
let new_path = newpath.get_cstr().map_err(|_| LinuxError::EINVAL)?;
if old_file_type == FileType::File {
let new_file = new_dir.dentry_open(
new_path,
OpenFlags::empty(),
).expect("can't find new file");
let new_file = new_dir
.dentry_open(new_path, OpenFlags::empty())
.expect("can't find new file");
// TODO: Check the file exists
let file_size = old_file.metadata().map_err(from_vfs)?.size;
let mut buffer = vec![0u8; file_size];
Expand All @@ -181,7 +180,6 @@ impl UserTaskContainer {
new_file.truncate(buffer.len()).map_err(from_vfs)?;
} else if old_file_type == FileType::Directory {
new_dir.mkdir(new_path).map_err(from_vfs)?;

} else {
panic!("can't handle the file: {:?} now", old_file_type);
}
Expand Down
49 changes: 1 addition & 48 deletions modules/devfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@
extern crate alloc;
extern crate log;

use core::mem::size_of;

use alloc::{collections::BTreeMap, string::ToString, sync::Arc, vec::Vec};
use sync::Mutex;
use vfscore::{
DirEntry, Dirent64, FileSystem, FileType, INodeInterface, StatMode, VfsError, VfsResult,
};
use vfscore::{DirEntry, FileSystem, FileType, INodeInterface, StatMode, VfsError, VfsResult};

mod cpu_dma_latency;
mod null;
Expand Down Expand Up @@ -44,7 +39,6 @@ impl FileSystem for DevFS {
fn root_dir(&self) -> Arc<dyn INodeInterface> {
Arc::new(DevDirContainer {
inner: self.root_dir.clone(),
dents_off: Mutex::new(0),
})
}

Expand All @@ -59,7 +53,6 @@ pub struct DevDir {

pub struct DevDirContainer {
inner: Arc<DevDir>,
dents_off: Mutex<usize>,
}

impl DevDir {
Expand Down Expand Up @@ -130,44 +123,4 @@ impl INodeInterface for DevDirContainer {
childrens: self.inner.map.len(),
})
}

fn getdents(&self, buffer: &mut [u8]) -> VfsResult<usize> {
let buf_ptr = buffer.as_mut_ptr() as usize;
let len = buffer.len();
let mut ptr: usize = buf_ptr;
let mut finished = 0;
for (i, x) in self
.inner
.map
.iter()
.enumerate()
.skip(*self.dents_off.lock())
{
let filename = x.0;
let file_bytes = filename.as_bytes();
let current_len = size_of::<Dirent64>() + file_bytes.len() + 1;
if len - (ptr - buf_ptr) < current_len {
break;
}

// let dirent = c2rust_ref(ptr as *mut Dirent);
let dirent: &mut Dirent64 = unsafe { (ptr as *mut Dirent64).as_mut() }.unwrap();

dirent.ino = 0;
dirent.off = current_len as i64;
dirent.reclen = current_len as u16;

dirent.ftype = 0; // 0 ftype is file

let buffer = unsafe {
core::slice::from_raw_parts_mut(dirent.name.as_mut_ptr(), file_bytes.len() + 1)
};
buffer[..file_bytes.len()].copy_from_slice(file_bytes);
buffer[file_bytes.len()] = b'\0';
ptr = ptr + current_len;
finished = i + 1;
}
*self.dents_off.lock() = finished;
Ok(ptr - buf_ptr)
}
}
50 changes: 44 additions & 6 deletions modules/executor/src/filetable.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use core::ops::{Deref, DerefMut};
use core::{
mem::size_of,
ops::{Deref, DerefMut},
};

use alloc::{string::String, sync::Arc, vec::Vec};
use fs::{
Expand All @@ -7,7 +10,7 @@ use fs::{
};
use sync::Mutex;
use vfscore::{
DirEntry, MMapFlags, Metadata, OpenFlags, PollEvent, SeekFrom, Stat, StatFS, TimeSpec,
DirEntry, Dirent64, MMapFlags, Metadata, OpenFlags, PollEvent, SeekFrom, Stat, StatFS, TimeSpec,
};

const FILE_MAX: usize = 255;
Expand Down Expand Up @@ -161,6 +164,45 @@ impl<'a> FileItem {
None => Err(VfsError::NotFile),
}
}

pub fn getdents(&self, buffer: &mut [u8]) -> Result<usize, VfsError> {
let buf_ptr = buffer.as_mut_ptr() as usize;
let len = buffer.len();
let mut ptr: usize = buf_ptr;
let mut finished = 0;
for (i, x) in self
.read_dir()?
.iter()
.enumerate()
.skip(*self.offset.lock())
{
let filename = &x.filename;
let file_bytes = filename.as_bytes();
let current_len = size_of::<Dirent64>() + file_bytes.len() + 1;
if len - (ptr - buf_ptr) < current_len {
break;
}

// let dirent = c2rust_ref(ptr as *mut Dirent);
let dirent: &mut Dirent64 = unsafe { (ptr as *mut Dirent64).as_mut() }.unwrap();

dirent.ino = 0;
dirent.off = current_len as i64;
dirent.reclen = current_len as u16;

dirent.ftype = 0; // 0 ftype is file

let buffer = unsafe {
core::slice::from_raw_parts_mut(dirent.name.as_mut_ptr(), file_bytes.len() + 1)
};
buffer[..file_bytes.len()].copy_from_slice(file_bytes);
buffer[file_bytes.len()] = b'\0';
ptr = ptr + current_len;
finished = i + 1;
}
*self.offset.lock() = finished;
Ok(ptr - buf_ptr)
}
}

impl INodeInterface for FileItem {
Expand Down Expand Up @@ -259,10 +301,6 @@ impl INodeInterface for FileItem {
self.inner.statfs(statfs)
}

fn getdents(&self, buffer: &mut [u8]) -> Result<usize, VfsError> {
self.inner.getdents(buffer)
}

fn utimes(&self, times: &mut [TimeSpec]) -> Result<(), VfsError> {
self.inner.utimes(times)
}
Expand Down
58 changes: 2 additions & 56 deletions modules/fs/src/fatfs_shim.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
use core::cmp::{self, min};
use core::mem::size_of;

use alloc::string::String;
use alloc::sync::Arc;
use devices::get_blk_device;
use fatfs::{Dir, Error, File, LossyOemCpConverter, NullTimeProvider};
use fatfs::{Read, Seek, SeekFrom, Write};
use frame_allocator::ceil_div;
use log::debug;
use sync::Mutex;
use vfscore::{
DirEntry, Dirent64, FileSystem, FileType, INodeInterface, Metadata, Stat, StatFS, StatMode,
VfsError, VfsResult,
DirEntry, FileSystem, FileType, INodeInterface, Metadata, Stat, StatFS, StatMode, VfsError,
VfsResult,
};

pub trait DiskOperation {
Expand All @@ -35,7 +33,6 @@ impl FileSystem for Fat32FileSystem {
fn root_dir(&'static self) -> Arc<dyn INodeInterface> {
Arc::new(FatDir {
filename: String::from(""),
dents_off: Mutex::new(0),
inner: self.inner.root_dir(),
})
}
Expand Down Expand Up @@ -74,7 +71,6 @@ unsafe impl Send for FatFile {}

pub struct FatDir {
filename: String,
dents_off: Mutex<usize>,
inner: Dir<'static, DiskCursor, NullTimeProvider, LossyOemCpConverter>,
}

Expand Down Expand Up @@ -185,7 +181,6 @@ impl INodeInterface for FatDir {
.create_dir(name)
.map(|dir| -> Arc<dyn INodeInterface> {
Arc::new(FatDir {
dents_off: Mutex::new(0),
filename: String::from(name),
inner: dir,
})
Expand Down Expand Up @@ -220,7 +215,6 @@ impl INodeInterface for FatDir {
let file = file.map(|x| x.unwrap()).ok_or(VfsError::FileNotFound)?;
if file.is_dir() {
Ok(Arc::new(FatDir {
dents_off: Mutex::new(0),
filename: String::from(name),
inner: file.to_dir(),
}))
Expand Down Expand Up @@ -314,54 +308,6 @@ impl INodeInterface for FatDir {
Ok(())
}

fn getdents(&self, buffer: &mut [u8]) -> VfsResult<usize> {
let buf_ptr = buffer.as_mut_ptr() as usize;
let len = buffer.len();
let mut ptr: usize = buf_ptr;
let mut finished = 0;
for (i, x) in self.inner.iter().enumerate().skip(*self.dents_off.lock()) {
let x = x.unwrap();
let filename = x.file_name();
if filename == "." || filename == ".." {
finished = i + 1;
continue;
}
let filename = filename;
let file_bytes = filename.as_bytes();
let current_len = ceil_div(size_of::<Dirent64>() + file_bytes.len() + 1, 8) * 8;
if len - (ptr - buf_ptr) < current_len {
break;
}

let dirent: &mut Dirent64 = unsafe { (ptr as *mut Dirent64).as_mut() }.unwrap();

dirent.ino = 1;
dirent.off = 0;
// dirent.off = (ptr - buf_ptr) as i64;
dirent.reclen = current_len as u16;

if x.is_dir() {
dirent.ftype = 4; // DT_DIR
} else {
dirent.ftype = 8; // DT_REF is 8
}

let buffer = unsafe {
core::slice::from_raw_parts_mut(
dirent.name.as_mut_ptr(),
current_len - size_of::<Dirent64>(),
)
};
buffer[..file_bytes.len()].copy_from_slice(file_bytes);
buffer[file_bytes.len()..].fill(0);

ptr = ptr + current_len;
finished = i + 1;
}
*self.dents_off.lock() = finished;
Ok(ptr - buf_ptr)
}

fn link(&self, _name: &str, _src: Arc<dyn INodeInterface>) -> VfsResult<()> {
// self.inner
// .open_file(name)
Expand Down
49 changes: 1 addition & 48 deletions modules/procfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ mod interrupts;
mod meminfo;
mod mounts;

use core::mem::size_of;

use alloc::{collections::BTreeMap, string::ToString, sync::Arc, vec::Vec};
use interrupts::Interrupts;
use meminfo::MemInfo;
use mounts::Mounts;
use sync::Mutex;
use vfscore::{
DirEntry, Dirent64, FileSystem, FileType, INodeInterface, StatMode, VfsError, VfsResult,
};
use vfscore::{DirEntry, FileSystem, FileType, INodeInterface, StatMode, VfsError, VfsResult};

pub struct ProcFS {
root: Arc<ProcDir>,
Expand All @@ -33,7 +28,6 @@ impl FileSystem for ProcFS {
fn root_dir(&'static self) -> Arc<dyn INodeInterface> {
Arc::new(DevDirContainer {
inner: self.root.clone(),
dents_off: Mutex::new(0),
})
}

Expand All @@ -58,7 +52,6 @@ impl ProcDir {

pub struct DevDirContainer {
inner: Arc<ProcDir>,
dents_off: Mutex<usize>,
}

impl INodeInterface for DevDirContainer {
Expand Down Expand Up @@ -106,44 +99,4 @@ impl INodeInterface for DevDirContainer {
childrens: self.inner.map.len(),
})
}

fn getdents(&self, buffer: &mut [u8]) -> VfsResult<usize> {
let buf_ptr = buffer.as_mut_ptr() as usize;
let len = buffer.len();
let mut ptr: usize = buf_ptr;
let mut finished = 0;
for (i, x) in self
.inner
.map
.iter()
.enumerate()
.skip(*self.dents_off.lock())
{
let filename = x.0;
let file_bytes = filename.as_bytes();
let current_len = size_of::<Dirent64>() + file_bytes.len() + 1;
if len - (ptr - buf_ptr) < current_len {
break;
}

// let dirent = c2rust_ref(ptr as *mut Dirent);
let dirent: &mut Dirent64 = unsafe { (ptr as *mut Dirent64).as_mut() }.unwrap();

dirent.ino = 0;
dirent.off = current_len as i64;
dirent.reclen = current_len as u16;

dirent.ftype = 0; // 0 ftype is file

let buffer = unsafe {
core::slice::from_raw_parts_mut(dirent.name.as_mut_ptr(), file_bytes.len() + 1)
};
buffer[..file_bytes.len()].copy_from_slice(file_bytes);
buffer[file_bytes.len()] = b'\0';
ptr = ptr + current_len;
finished = i + 1;
}
*self.dents_off.lock() = finished;
Ok(ptr - buf_ptr)
}
}
Loading

0 comments on commit c2ae46c

Please sign in to comment.