Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion easy-fs-fuse/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ edition = "2018"
[dependencies]
clap = "2.33.3"
easy-fs = { path = "../easy-fs" }
rand = "0.8.0"
zerocopy = "=0.7.35"
rand = "=0.8.4"
ppv-lite86 = "=0.2.17"

# [features]
# board_qemu = []
Expand Down
4 changes: 4 additions & 0 deletions easy-fs/src/block_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ impl BlockCache {
self.block_device.write_block(self.block_id, &self.cache);
}
}
pub fn which_device(&self) -> u64 {
// self.block_device
0
}
}

impl Drop for BlockCache {
Expand Down
8 changes: 8 additions & 0 deletions easy-fs/src/efs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,12 @@ impl EasyFileSystem {
(block_id - self.data_area_start_block) as usize,
)
}
/// Get inode id from block_id and block_offset
pub fn get_disk_inode_id(&self, block_id: u32, block_offset: usize) -> u32 {
// inode_id = (当前块号 - Inode区起始块号) * 每个块能存的 Inode 数 + 块内偏移索引
let inodes_per_block = BLOCK_SZ / core::mem::size_of::<DiskInode>();
let relative_block = block_id - self.inode_area_start_block;
(relative_block * inodes_per_block as u32)
+ (block_offset / core::mem::size_of::<DiskInode>()) as u32
}
}
5 changes: 4 additions & 1 deletion easy-fs/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl SuperBlock {
}
}

#[derive(PartialEq)]
#[derive(PartialEq, Clone)]
pub enum DiskInodeType {
File,
Directory,
Expand All @@ -68,8 +68,10 @@ type IndirectBlock = [u32; BLOCK_SZ / 4];
type DataBlock = [u8; BLOCK_SZ];

#[repr(C)]
#[derive(PartialEq, Clone)]
pub struct DiskInode {
pub size: u32,
pub nlink: u32,
pub direct: [u32; INODE_DIRECT_COUNT],
pub indirect1: u32,
pub indirect2: u32,
Expand All @@ -80,6 +82,7 @@ impl DiskInode {
/// indirect1 and indirect2 block are allocated only when they are needed.
pub fn initialize(&mut self, type_: DiskInodeType) {
self.size = 0;
self.nlink = 1;
self.direct.iter_mut().for_each(|v| *v = 0);
self.indirect1 = 0;
self.indirect2 = 0;
Expand Down
126 changes: 126 additions & 0 deletions easy-fs/src/vfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,130 @@ impl Inode {
});
block_cache_sync_all();
}

/// Delete entry from name
fn delete_entry_from_name(&self, name: &str, disk_inode: &mut DiskInode) -> Option<u32> {
// assert it is a directory
assert!(disk_inode.is_dir());
let file_count = (disk_inode.size as usize) / DIRENT_SZ;
let mut dirent = DirEntry::empty();
for i in 0..file_count {
assert_eq!(
disk_inode.read_at(DIRENT_SZ * i, dirent.as_bytes_mut(), &self.block_device,),
DIRENT_SZ,
);
if dirent.name() == name {
let mut replace_entry = DirEntry::empty();
if i != file_count - 1 {
assert_eq!(
disk_inode.read_at(
DIRENT_SZ * (file_count - 1),
replace_entry.as_bytes_mut(),
&self.block_device,
),
DIRENT_SZ,
);
}
assert_eq!(
disk_inode.write_at(
DIRENT_SZ * i,
replace_entry.as_bytes_mut(),
&self.block_device,
),
DIRENT_SZ,
);
disk_inode.size -= DIRENT_SZ as u32;
return Some(dirent.inode_id());
}
}
None
}

/// Hard link current inode to another name under root directory
pub fn linkat(&self, name: &str) -> bool {
let mut fs = self.fs.lock();
let inode_id = fs.get_disk_inode_id(self.block_id as u32, self.block_offset);
get_block_cache(self.block_id as usize, Arc::clone(&self.block_device))
.lock()
.modify(self.block_offset, |inode: &mut DiskInode| {
inode.nlink += 1;
});

let (root_block_id, root_block_offset) = fs.get_disk_inode_pos(0);
let res = get_block_cache(root_block_id as usize, Arc::clone(&self.block_device))
.lock()
.modify(root_block_offset, |root_node: &mut DiskInode| {
assert!(root_node.is_dir());

if self.find_inode_id(name, root_node).is_some() {
return false;
}

let size = root_node.size;
let new_size = root_node.size + DIRENT_SZ as u32;
self.increase_size(new_size, root_node, &mut fs);

let dirent = DirEntry::new(name, inode_id);
root_node.write_at(size as usize, dirent.as_bytes(), &self.block_device);
true
});
block_cache_sync_all();
res
}
/// Unlink an entry from root with name
pub fn unlinkat(&self, name: &str) -> bool {
let mut fs = self.fs.lock();

let (root_block_id, root_block_offset) = fs.get_disk_inode_pos(0);
let target_inode_id =
get_block_cache(root_block_id as usize, Arc::clone(&self.block_device))
.lock()
.modify(root_block_offset, |root_node: &mut DiskInode| {
assert!(root_node.is_dir());

// Find name in root directory
// Replace entry with latest entry
// Decrease root directory
self.delete_entry_from_name(name, root_node)
});

// Decrease target disknode nlink
let inode_id = match target_inode_id {
Some(id) => id,
None => return false,
};

let (target_block, target_offset) = fs.get_disk_inode_pos(inode_id);
get_block_cache(target_block as usize, Arc::clone(&self.block_device))
.lock()
.modify(target_offset, |inode: &mut DiskInode| {
inode.nlink -= 1;
if inode.nlink == 0 {
let size = inode.size;
let data_blocks_dealloc = inode.clear_size(&self.block_device);
assert!(data_blocks_dealloc.len() == DiskInode::total_blocks(size) as usize);
for data_block in data_blocks_dealloc.into_iter() {
fs.dealloc_data(data_block);
}
}
});

block_cache_sync_all();
true
}
/// get inode info
pub fn stat(&self) -> (u64, u64, Option<bool>, Option<u32>) {
let fs = self.fs.lock();
let inode = fs.get_disk_inode_id(self.block_id as u32, self.block_offset);
let dev = get_block_cache(self.block_id as usize, Arc::clone(&self.block_device))
.lock()
.which_device();
let mut is_dir = None;
let mut nlink = None;
self.modify_disk_inode(|disk_inode| {
is_dir = Some(disk_inode.is_dir());
nlink = Some(disk_inode.nlink);
});
(dev, inode as u64, is_dir, nlink)
}
}
3 changes: 1 addition & 2 deletions os/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ log = "0.4"
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
xmas-elf = "0.7.0"
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" }
easy-fs = { path = "../easy-fs" }

easy-fs = { path = "../easy-fs" }
4 changes: 4 additions & 0 deletions os/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ pub const CLOCK_FREQ: usize = 12500000;
pub const MEMORY_END: usize = 0x88000000;
/// The base address of control registers in Virtio_Block device
pub const MMIO: &[(usize, usize)] = &[(0x10001000, 0x1000)];
/// Max syscall num
pub const MAX_SYSCALL_NUM: usize = 500;
/// Prior process manager BigStride
pub const BIG_STRIDE: u8 = 2<<6;
25 changes: 24 additions & 1 deletion os/src/fs/inode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
//! `UPSafeCell<OSInodeInner>` -> `OSInode`: for static `ROOT_INODE`,we
//! need to wrap `OSInodeInner` into `UPSafeCell`
use super::File;
use crate::drivers::BLOCK_DEVICE;
use crate::{drivers::BLOCK_DEVICE, fs::StatMode};
use crate::mm::UserBuffer;
use crate::sync::UPSafeCell;
use alloc::sync::Arc;
use alloc::vec::Vec;
use bitflags::*;
use easy_fs::{EasyFileSystem, Inode};
use lazy_static::*;
use crate::fs::Stat;

/// inode in memory
/// A wrapper around a filesystem inode
Expand Down Expand Up @@ -53,6 +54,14 @@ impl OSInode {
}
v
}
/// link current OSInode to name
pub fn linkat(&self,name:&str)->bool{
self.inner.exclusive_access().inode.linkat(name)
}
/// unlink name from rootinode
pub fn unlinkat(&self,name:&str)->bool{
self.inner.exclusive_access().inode.unlinkat(name)
}
}

lazy_static! {
Expand Down Expand Up @@ -156,4 +165,18 @@ impl File for OSInode {
}
total_write_size
}
fn stat(&self, st:&mut Stat) {
let(dev,ino,is_dir,nlink)=self.inner.exclusive_access().inode.stat();
st.dev=dev;
st.ino=ino;
st.mode= match is_dir {
Some(true) => StatMode::DIR,
Some(false) => StatMode::FILE,
None => StatMode::NULL,
};
st.nlink=match nlink{
Some(val)=>val,
None=>0,
}
}
}
4 changes: 4 additions & 0 deletions os/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub trait File: Send + Sync {
fn read(&self, buf: UserBuffer) -> usize;
/// write to the file from buf, return the number of bytes written
fn write(&self, buf: UserBuffer) -> usize;
/// provide file state
fn stat(&self, st: &mut Stat);
}

/// The stat of a inode
Expand Down Expand Up @@ -44,6 +46,8 @@ bitflags! {
const DIR = 0o040000;
/// ordinary regular file
const FILE = 0o100000;
/// pipe
const PIPE = 0o010000;
}
}

Expand Down
7 changes: 7 additions & 0 deletions os/src/fs/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::File;
use crate::fs::StatMode;
use crate::mm::UserBuffer;
use crate::sync::UPSafeCell;
use alloc::sync::{Arc, Weak};
Expand Down Expand Up @@ -173,4 +174,10 @@ impl File for Pipe {
}
}
}
fn stat(&self, st: &mut super::Stat) {
st.dev = 0;
st.ino = 0;
st.mode = StatMode::PIPE;
st.nlink = 1;
}
}
13 changes: 13 additions & 0 deletions os/src/fs/stdio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//!Stdin & Stdout
use super::File;
use crate::fs::StatMode;
use crate::mm::UserBuffer;
use crate::sbi::console_getchar;
use crate::task::suspend_current_and_run_next;
Expand Down Expand Up @@ -39,6 +40,12 @@ impl File for Stdin {
fn write(&self, _user_buf: UserBuffer) -> usize {
panic!("Cannot write to stdin!");
}
fn stat(&self, st:&mut super::Stat) {
st.dev=0;
st.ino=0;
st.mode=StatMode::NULL;
st.nlink=0;
}
}

impl File for Stdout {
Expand All @@ -57,4 +64,10 @@ impl File for Stdout {
}
user_buf.len()
}
fn stat(&self, st:&mut super::Stat) {
st.dev=0;
st.ino=0;
st.mode=StatMode::NULL;
st.nlink=0;
}
}
8 changes: 8 additions & 0 deletions os/src/mm/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ where
pub fn get_end(&self) -> T {
self.r
}
pub fn is_overlap(&self,l:T,r:T)->Option<bool>{
if l >= r { return None; }
if l < self.r && self.l < r {
Some(true)
} else {
Some(false)
}
}
}
impl<T> IntoIterator for SimpleRange<T>
where
Expand Down
Loading