Skip to content

Commit 9caa4de

Browse files
committed
ch6 ok
1 parent 89fd5bb commit 9caa4de

File tree

7 files changed

+184
-10
lines changed

7 files changed

+184
-10
lines changed

easy-fs/src/efs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl EasyFileSystem {
7676
get_block_cache(root_inode_block_id as usize, Arc::clone(&block_device))
7777
.lock()
7878
.modify(root_inode_offset, |disk_inode: &mut DiskInode| {
79-
disk_inode.initialize(DiskInodeType::Directory);
79+
disk_inode.initialize(DiskInodeType::Directory, 0);
8080
});
8181
block_cache_sync_all();
8282
Arc::new(Mutex::new(efs))

easy-fs/src/layout.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,20 @@ pub struct DiskInode {
8686
pub indirect1: u32,
8787
pub indirect2: u32,
8888
type_: DiskInodeType,
89+
nlink: u32,
90+
inode_id: u32,
8991
}
9092

9193
impl DiskInode {
9294
/// Initialize a disk inode, as well as all direct inodes under it
9395
/// indirect1 and indirect2 block are allocated only when they are needed
94-
pub fn initialize(&mut self, type_: DiskInodeType) {
96+
pub fn initialize(&mut self, type_: DiskInodeType, inode_id: u32) {
9597
self.size = 0;
9698
self.direct.iter_mut().for_each(|v| *v = 0);
9799
self.indirect1 = 0;
98100
self.indirect2 = 0;
99101
self.type_ = type_;
102+
self.inode_id = inode_id;
100103
}
101104
/// Whether this inode is a directory
102105
pub fn is_dir(&self) -> bool {
@@ -387,6 +390,10 @@ impl DiskInode {
387390
}
388391
write_size
389392
}
393+
/// ino
394+
pub fn ino(&self) -> u32 {
395+
self.inode_id
396+
}
390397
}
391398
/// A directory entry
392399
#[repr(C)]

easy-fs/src/vfs.rs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl Inode {
110110
get_block_cache(new_inode_block_id as usize, Arc::clone(&self.block_device))
111111
.lock()
112112
.modify(new_inode_block_offset, |new_inode: &mut DiskInode| {
113-
new_inode.initialize(DiskInodeType::File);
113+
new_inode.initialize(DiskInodeType::File, new_inode_id);
114114
});
115115
self.modify_disk_inode(|root_inode| {
116116
// append file in the dirent
@@ -183,4 +183,93 @@ impl Inode {
183183
});
184184
block_cache_sync_all();
185185
}
186+
/// is dir?
187+
pub fn is_dir(&self) -> bool {
188+
self.read_disk_inode(|disk_inode| {
189+
disk_inode.is_dir()
190+
})
191+
}
192+
/// is file?
193+
pub fn is_file(&self) -> bool {
194+
self.read_disk_inode(|disk_inode|{
195+
disk_inode.is_file()
196+
})
197+
}
198+
/// get nlink
199+
pub fn nlink(&self, inode_id: u32) -> u32 {
200+
let _fs = self.fs.lock();
201+
self.read_disk_inode(|disk_inode| {
202+
let file_count = (disk_inode.size as usize) / DIRENT_SZ;
203+
let mut dirent = DirEntry::empty();
204+
let mut count = 0;
205+
for i in 0..file_count {
206+
assert_eq!(
207+
disk_inode.read_at(DIRENT_SZ * i, dirent.as_bytes_mut(), &self.block_device,),
208+
DIRENT_SZ,
209+
);
210+
if dirent.inode_id() == inode_id {
211+
count += 1;
212+
}
213+
}
214+
count
215+
})
216+
}
217+
/// ino
218+
pub fn ino(&self) -> u32 {
219+
self.read_disk_inode(|disk_inode| {
220+
disk_inode.ino()
221+
})
222+
}
223+
/// Link new inode to current inode
224+
pub fn linkat(&self, old_name: &str, new_name: &str) -> isize {
225+
if let Some(inode_id) = self.read_disk_inode(|disk_inode| {
226+
self.find_inode_id(old_name, disk_inode)
227+
}) {
228+
let mut fs = self.fs.lock();
229+
let (new_inode_block_id, new_inode_block_offset) = fs.get_disk_inode_pos(inode_id as u32);
230+
get_block_cache(new_inode_block_id as usize, Arc::clone(&self.block_device))
231+
.lock()
232+
.modify(new_inode_block_offset, |new_inode: &mut DiskInode| {
233+
new_inode.initialize(DiskInodeType::File, inode_id);
234+
});
235+
self.modify_disk_inode(|disk_inode| {
236+
let file_count = (disk_inode.size as usize) / DIRENT_SZ;
237+
let new_size = (file_count + 1) * DIRENT_SZ;
238+
// increase size
239+
self.increase_size(new_size as u32, disk_inode, &mut fs);
240+
let dirent = DirEntry::new(new_name, inode_id as u32);
241+
disk_inode.write_at(
242+
file_count * DIRENT_SZ,
243+
dirent.as_bytes(),
244+
&self.block_device,
245+
);
246+
});
247+
block_cache_sync_all();
248+
0
249+
} else {
250+
-1
251+
}
252+
}
253+
/// Un Link inode
254+
pub fn unlinkat(&self, name: &str) -> isize {
255+
self.modify_disk_inode(|root_inode| {
256+
let file_count = (root_inode.size as usize) / DIRENT_SZ;
257+
let mut dirent = DirEntry::empty();
258+
for i in 0..file_count {
259+
assert_eq!(
260+
root_inode.read_at(DIRENT_SZ * i, dirent.as_bytes_mut(), &self.block_device,),
261+
DIRENT_SZ,
262+
);
263+
if dirent.name() == name {
264+
root_inode.write_at(
265+
i * DIRENT_SZ,
266+
DirEntry::empty().as_bytes(),
267+
&self.block_device
268+
);
269+
return 0;
270+
}
271+
}
272+
-1
273+
})
274+
}
186275
}

os/src/fs/inode.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! `UPSafeCell<OSInodeInner>` -> `OSInode`: for static `ROOT_INODE`,we
66
//! need to wrap `OSInodeInner` into `UPSafeCell`
7-
use super::File;
7+
use super::{File, Stat, StatMode};
88
use crate::drivers::BLOCK_DEVICE;
99
use crate::mm::UserBuffer;
1010
use crate::sync::UPSafeCell;
@@ -125,6 +125,16 @@ pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
125125
}
126126
}
127127

128+
/// Linkat a file
129+
pub fn linkat(old_name: &str, new_name: &str) -> isize {
130+
ROOT_INODE.linkat(old_name, new_name)
131+
}
132+
133+
/// UnLinkat a file
134+
pub fn unlinkat(name: &str) -> isize {
135+
ROOT_INODE.unlinkat(name)
136+
}
137+
128138
impl File for OSInode {
129139
fn readable(&self) -> bool {
130140
self.readable
@@ -156,4 +166,18 @@ impl File for OSInode {
156166
}
157167
total_write_size
158168
}
169+
fn stat(&self, _st: *mut Stat) -> usize {
170+
let inner = self.inner.exclusive_access();
171+
if inner.inode.is_dir() {
172+
unsafe { (*_st).mode = StatMode::DIR };
173+
} else if inner.inode.is_file() {
174+
unsafe { (*_st).mode = StatMode::FILE};
175+
} else {
176+
unsafe { (*_st).mode = StatMode::NULL};
177+
}
178+
179+
unsafe { (*_st).ino = inner.inode.ino() as u64 };
180+
unsafe { (*_st).nlink = ROOT_INODE.nlink(inner.inode.ino()) };
181+
0
182+
}
159183
}

os/src/fs/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ pub trait File: Send + Sync {
1515
fn read(&self, buf: UserBuffer) -> usize;
1616
/// write to the file from buf, return the number of bytes written
1717
fn write(&self, buf: UserBuffer) -> usize;
18+
/// stat mode
19+
fn stat(&self, _st: *mut Stat) -> usize {
20+
0
21+
}
1822
}
1923

2024
/// The stat of a inode
@@ -46,5 +50,5 @@ bitflags! {
4650
}
4751
}
4852

49-
pub use inode::{list_apps, open_file, OSInode, OpenFlags};
53+
pub use inode::{list_apps, open_file, linkat, unlinkat, OSInode, OpenFlags};
5054
pub use stdio::{Stdin, Stdout};

os/src/syscall/fs.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! File and filesystem-related syscalls
2-
use crate::fs::{open_file, OpenFlags, Stat};
3-
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer};
2+
use crate::fs::{linkat, unlinkat, open_file, OpenFlags, Stat};
3+
use crate::mm::{translated_byte_buffer, translated_physaddr, translated_str, UserBuffer};
44
use crate::task::{current_task, current_user_token};
55

66
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
@@ -81,7 +81,27 @@ pub fn sys_fstat(_fd: usize, _st: *mut Stat) -> isize {
8181
"kernel:pid[{}] sys_fstat NOT IMPLEMENTED",
8282
current_task().unwrap().pid.0
8383
);
84-
-1
84+
let task = current_task().unwrap();
85+
let inner = task.inner_exclusive_access();
86+
if _fd >= inner.fd_table.len() {
87+
debug!("fd > len()");
88+
return -1;
89+
}
90+
if inner.fd_table[_fd].is_none() {
91+
debug!("fd is none");
92+
return -1;
93+
}
94+
if let Some(file) = &inner.fd_table[_fd] {
95+
let file = file.clone();
96+
drop(inner);
97+
let pa = translated_physaddr(current_user_token(), _st as *const u8);
98+
let phy_st = pa.0 as *mut Stat;
99+
file.stat(phy_st);
100+
0
101+
} else {
102+
-1
103+
}
104+
85105
}
86106

87107
/// YOUR JOB: Implement linkat.
@@ -90,7 +110,13 @@ pub fn sys_linkat(_old_name: *const u8, _new_name: *const u8) -> isize {
90110
"kernel:pid[{}] sys_linkat NOT IMPLEMENTED",
91111
current_task().unwrap().pid.0
92112
);
93-
-1
113+
let token = current_user_token();
114+
let old_name = translated_str(token, _old_name);
115+
let new_name = translated_str(token, _new_name);
116+
if old_name == new_name {
117+
return -1;
118+
}
119+
linkat(old_name.as_str(), new_name.as_str())
94120
}
95121

96122
/// YOUR JOB: Implement unlinkat.
@@ -99,5 +125,7 @@ pub fn sys_unlinkat(_name: *const u8) -> isize {
99125
"kernel:pid[{}] sys_unlinkat NOT IMPLEMENTED",
100126
current_task().unwrap().pid.0
101127
);
102-
-1
128+
let token = current_user_token();
129+
let name = translated_str(token, _name);
130+
unlinkat(name.as_str())
103131
}

reports/lab4.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
### 总结实现的功能
2+
1. 由于获取加载应用程序的机制发生了改变,所以修改`sys_spawn`系统调用,通过文件系统读取进程。
3+
2. 实现了`sys_linkat``sys_unlinkat`系统调用,主要通过root inode节点写入与清空 DirEntry 实现
4+
3. 实现了`sys_fstat`系统调用
5+
6+
### 问答题
7+
#### 在我们的easy-fs中,root inode起着什么作用?如果root inode中的内容损坏了,会发生什么?
8+
9+
root inode对应到我们的根目录,可以检索该目录下所有的文件,如果损坏,将无法访问该目录下的文件
10+
11+
### 荣誉准则
12+
1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:
13+
14+
向claude3.7老师请教了许多问题,感谢它的帮助
15+
16+
2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:
17+
18+
参考了 https://cheats.rs/ 手册的一些语法细节。
19+
20+
3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。
21+
22+
4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

0 commit comments

Comments
 (0)