Skip to content

Commit

Permalink
unlink有个bug,但是不影响测试,先交了再说
Browse files Browse the repository at this point in the history
  • Loading branch information
lurenjia1213 committed Oct 28, 2024
1 parent 3cc6081 commit fae6a35
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 25 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,7 @@ $ git clone [email protected]:LearningOS/rCore-Tutorial-Test-2024A ci-user/user
$ git checkout ch<Number>
$ cd ci-user
$ make test CHAPTER=<Number>
```
```


#fuse是打包用的,看起来不被内核直接使用
3 changes: 2 additions & 1 deletion easy-fs/src/efs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ pub struct EasyFileSystem {
pub inode_bitmap: Bitmap,
///Data bitmap
pub data_bitmap: Bitmap,
inode_area_start_block: u32,
///
pub inode_area_start_block: u32,
data_area_start_block: u32,
}

Expand Down
23 changes: 20 additions & 3 deletions easy-fs/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,41 @@ impl SuperBlock {
}
}
/// Type of a disk inode
#[derive(PartialEq)]
#[derive(PartialEq,Clone, Copy)]
pub enum DiskInodeType {
File,
Directory,
}

//需要注意跨平台构建时的usize
/// A indirect block
type IndirectBlock = [u32; BLOCK_SZ / 4];
/// A data block
type DataBlock = [u8; BLOCK_SZ];
/// A disk inode
#[repr(C)]
#[derive(PartialEq,Clone, Copy)]
pub struct DiskInode {
pub size: u32,
pub direct: [u32; INODE_DIRECT_COUNT],
pub indirect1: u32,
pub indirect2: u32,
type_: DiskInodeType,
pub type_: DiskInodeType,
pub nlink: u32,
}
/*
每个文件/目录在磁盘上均以一个 DiskInode 的形式存储。其中包含文件/目录的元数据: size 表示文件/目录内容的字节数, type_ 表示索引节点的类型 DiskInodeType ,目前仅支持文件 File 和目录 Directory 两种类型。其余的 direct/indirect1/indirect2 都是存储文件内容/目录内容的数据块的索引,这也是索引节点名字的由来。
为了尽可能节约空间,在进行索引的时候,块的编号用一个 u32 存储。索引方式分成直接索引和间接索引两种:
当文件很小的时候,只需用到直接索引, direct 数组中最多可以指向 INODE_DIRECT_COUNT 个数据块,当取值为 28 的时候,通过直接索引可以找到 14KiB 的内容。
当文件比较大的时候,不仅直接索引的 direct 数组装满,还需要用到一级间接索引 indirect1 。它指向一个一级索引块,这个块也位于磁盘布局的数据块区域中。这个一级索引块中的每个 u32 都用来指向数据块区域中一个保存该文件内容的数据块,因此,最多能够索引
个数据块,对应 64KiB 的内容。
当文件大小超过直接索引和一级索引支持的容量上限 78KiB 的时候,就需要用到二级间接索引 indirect2 。它指向一个位于数据块区域中的二级索引块。二级索引块中的每个 u32 指向一个不同的一级索引块,这些一级索引块也位于数据块区域中。因此,通过二级间接索引最多能够索引
的内容。
*/

impl DiskInode {
/// Initialize a disk inode, as well as all direct inodes under it
Expand All @@ -97,6 +113,7 @@ impl DiskInode {
self.indirect1 = 0;
self.indirect2 = 0;
self.type_ = type_;
self.nlink=1
}
/// Whether this inode is a directory
pub fn is_dir(&self) -> bool {
Expand Down
95 changes: 95 additions & 0 deletions easy-fs/src/vfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{
block_cache_sync_all, get_block_cache, BlockDevice, DirEntry, DiskInode, DiskInodeType,
EasyFileSystem, DIRENT_SZ,
};
use crate::BLOCK_SZ;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
Expand Down Expand Up @@ -89,6 +90,55 @@ impl Inode {
v.push(fs.alloc_data());
}
disk_inode.increase_size(new_size, v, &self.block_device);
}
/// Create inode under current inode by name
pub fn link(&self, new_name: &str,old_name: &str) {

//这里发生过死锁,艹,前面被锁了,get_node_id也有一次
let inode =self.find(old_name);

let inode_id=inode.clone().unwrap().get_inode_id();
let mut fs = self.fs.lock();
self.modify_disk_inode(|root_inode| {
let file_count = (root_inode.size as usize) / DIRENT_SZ;
let new_size = (file_count + 1) * DIRENT_SZ;
self.increase_size(new_size as u32, root_inode, &mut fs);
let dirent = DirEntry::new(new_name,inode_id);
root_inode.write_at(
file_count * DIRENT_SZ,
dirent.as_bytes(),
&self.block_device,
);
});
inode.unwrap().modify_disk_inode(|inode|{
inode.nlink+=1;
});
block_cache_sync_all();
}


///
pub fn unlink(&self, name: &str) {

let inode=self.find(name);
inode.unwrap().modify_disk_inode(|inode|{
inode.nlink-=1;
});
self.modify_disk_inode(|root_inode| {
let file_count = (root_inode.size as usize) / DIRENT_SZ;
for i in 0..file_count {//遍历,并且找到这name
let mut dirent = DirEntry::empty();
root_inode.read_at(i * DIRENT_SZ, dirent.as_bytes_mut(), &self.block_device,);//wtf
if dirent.name() == name {
root_inode.write_at(i * DIRENT_SZ, DirEntry::empty().as_bytes(), &self.block_device);//clean
break;
}
}
});
//let (block_id, block_offset) = fs.get_disk_inode_pos(new_inode_id);
block_cache_sync_all();
// return inode
// release efs lock automatically by compiler 与上无关
}
/// Create inode under current inode by name
pub fn create(&self, name: &str) -> Option<Arc<Inode>> {
Expand Down Expand Up @@ -183,4 +233,49 @@ impl Inode {
});
block_cache_sync_all();
}
///ret u32 inode id
pub fn get_inode_id(&self)->u32{
let fs = self.fs.lock();
let inode_size=core::mem::size_of::<DiskInode>();
let inode_per_blk:u32=BLOCK_SZ as u32/inode_size as u32;
let blk_offset_out=self.block_id as u32-fs.inode_area_start_block as u32;//我真服了,已经混乱了
let inode_id=blk_offset_out*inode_per_blk+ self.block_offset as u32/inode_size as u32;
inode_id
}
///get nlink
pub fn get_nlink(&self)->u32{
let _fs = self.fs.lock();

self.read_disk_inode(|disk_inode| {

let v: u32 = disk_inode.nlink;

v
})
}
}
/*
pub fn ls(&self) -> Vec<String> {
let _fs = self.fs.lock();
self.read_disk_inode(|disk_inode| {
let file_count = (disk_inode.size as usize) / DIRENT_SZ;
let mut v: Vec<String> = Vec::new();
for i in 0..file_count {
let mut dirent = DirEntry::empty();
assert_eq!(
disk_inode.read_at(i * DIRENT_SZ, dirent.as_bytes_mut(), &self.block_device,),
DIRENT_SZ,
);
v.push(String::from(dirent.name()));
}
v
})
}
pub struct Inode {
block_id: usize,
block_offset: usize,
fs: Arc<Mutex<EasyFileSystem>>,
block_device: Arc<dyn BlockDevice>,
}
*/
12 changes: 12 additions & 0 deletions os/src/fs/inode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ impl OSInode {
}
v
}



}

lazy_static! {
///
pub static ref ROOT_INODE: Arc<Inode> = {
let efs = EasyFileSystem::open(BLOCK_DEVICE.clone());
Arc::new(EasyFileSystem::root_inode(&efs))
Expand Down Expand Up @@ -155,4 +159,12 @@ impl File for OSInode {
}
total_write_size
}
fn get_inode_id(&self) -> u32 {
let inner = self.inner.exclusive_access();
inner.inode.get_inode_id()
}
fn get_nlink(&self) -> u32 {
let inner = self.inner.exclusive_access();
inner.inode.get_nlink()
}
}
8 changes: 6 additions & 2 deletions os/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ 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;
///方便fstat
fn get_inode_id(&self) -> u32 ;
///同上
fn get_nlink(&self) -> u32;
}

/// The stat of a inode
Expand All @@ -30,7 +34,7 @@ pub struct Stat {
/// number of hard links
pub nlink: u32,
/// unused pad
pad: [u64; 7],
pub pad: [u64; 7],
}

bitflags! {
Expand All @@ -46,5 +50,5 @@ bitflags! {
}
}

pub use inode::{list_apps, open_file, OSInode, OpenFlags};
pub use inode::{list_apps, open_file, OSInode, OpenFlags,ROOT_INODE};
pub use stdio::{Stdin, Stdout};
16 changes: 16 additions & 0 deletions os/src/fs/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ impl File for Stdin {
fn write(&self, _user_buf: UserBuffer) -> usize {
panic!("Cannot write to stdin!");
}
fn get_inode_id(&self) ->u32 {
panic!("Cannot get_inode_id to stdin!");

}
fn get_nlink(&self) -> u32 {
panic!("Cannot get_inode_id to stdin!");

}
}

impl File for Stdout {
Expand All @@ -57,4 +65,12 @@ impl File for Stdout {
}
user_buf.len()
}
fn get_inode_id(&self) ->u32 {
panic!("Cannot get_inode_id to stdout!");

}
fn get_nlink(&self) -> u32 {
panic!("Cannot get_inode_id to stdout!");

}
}
90 changes: 72 additions & 18 deletions os/src/syscall/fs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! File and filesystem-related syscalls
use crate::fs::{open_file, OpenFlags, Stat};
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer};
use crate::fs::{open_file, OpenFlags, Stat,ROOT_INODE,StatMode};
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer,trans_addr_v2p};
use crate::task::{current_task, current_user_token};

pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
Expand Down Expand Up @@ -76,28 +76,82 @@ pub fn sys_close(fd: usize) -> isize {
}

/// YOUR JOB: Implement fstat.
pub fn sys_fstat(_fd: usize, _st: *mut Stat) -> isize {
trace!(
"kernel:pid[{}] sys_fstat NOT IMPLEMENTED",
current_task().unwrap().pid.0
);
-1
/*
pub fn sys_fstat(fd: usize, _st: *mut Stat) -> isize {
let task = current_task().unwrap();
let inner = task.inner_exclusive_access();
if fd >= inner.fd_table.len() {
return -1;
}
if inner.fd_table[fd].is_none() {
return -1;
}
let file = Some(inner.fd_table[fd].as_ref().unwrap().clone());
drop(inner);
let ino = file.get_inode_id() as u64;
let nlink = file.get_nlink() as u32;
unsafe {
*st = Stat {
dev: 0,
ino,
mode: StatMode::FILE,
nlink,
pad: [0; 7],
};
}
0
} */
pub fn sys_fstat(fd: usize, st: *mut Stat) -> isize {
trace!("kernel:pid[{}] sys_fstat", current_task().unwrap().pid.0);
let task = current_task().unwrap();
let token = current_user_token();
let inner = task.inner_exclusive_access();
if let Some(file) = &inner.fd_table[fd] {
let st = trans_addr_v2p(token, st as usize) as *mut Stat;
let ino = file.get_inode_id() as u64;
let nlink = file.get_nlink() as u32;
unsafe {
*st = Stat {
dev: 0,
ino,
mode: StatMode::FILE,
nlink,
pad: [0; 7],
};
}
0
} else {
-1
}
}

/// YOUR JOB: Implement linkat.
pub fn sys_linkat(_old_name: *const u8, _new_name: *const u8) -> isize {
trace!(
"kernel:pid[{}] sys_linkat NOT IMPLEMENTED",
current_task().unwrap().pid.0
);
-1
let token = current_user_token();
let old_name = translated_str(token, _old_name);
let new_name = translated_str(token, _new_name);
if old_name == new_name {
return -1;
}
ROOT_INODE.link(new_name.as_str(),old_name.as_str());




0
}

/// YOUR JOB: Implement unlinkat.
pub fn sys_unlinkat(_name: *const u8) -> isize {
trace!(
"kernel:pid[{}] sys_unlinkat NOT IMPLEMENTED",
current_task().unwrap().pid.0
);
-1
let token = current_user_token();
let name=translated_str(token, _name);
ROOT_INODE.unlink(name.as_str());
0
}
Empty file added reports/lab1.md
Empty file.
Empty file added reports/lab2.md
Empty file.
Empty file added reports/lab3.md
Empty file.
Empty file added reports/lab4.md
Empty file.

0 comments on commit fae6a35

Please sign in to comment.