Skip to content

Commit 1346fb1

Browse files
committed
Refactor easy-fs
1 parent 12c6c53 commit 1346fb1

File tree

14 files changed

+329
-278
lines changed

14 files changed

+329
-278
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ os/Cargo.lock
66
user/target/*
77
user/.idea/*
88
user/Cargo.lock
9+
easy-fs/Cargo.lock
10+
easy-fs/target/*
11+
easy-fs-fuse/Cargo.lock
12+
easy-fs-fuse/target/*
913
tools/

easy-fs-fuse/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "easy-fs-fuse"
3+
version = "0.1.0"
4+
authors = ["Yifan Wu <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
clap = "2.33.3"
11+
easy-fs = { path = "../easy-fs" }
12+
rand = "0.8.0"

easy-fs/src/bin/main.rs renamed to easy-fs-fuse/src/main.rs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
extern crate easy_fs;
2-
extern crate alloc;
3-
41
use easy_fs::{
52
BlockDevice,
63
EasyFileSystem,
74
};
85
use std::fs::{File, OpenOptions, read_dir};
96
use std::io::{Read, Write, Seek, SeekFrom};
107
use std::sync::Mutex;
11-
use alloc::sync::Arc;
8+
use std::sync::Arc;
9+
use clap::{Arg, App};
1210

1311
const BLOCK_SZ: usize = 512;
1412

@@ -34,15 +32,30 @@ fn main() {
3432
easy_fs_pack().expect("Error when packing easy-fs!");
3533
}
3634

37-
static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";
38-
3935
fn easy_fs_pack() -> std::io::Result<()> {
36+
let matches = App::new("EasyFileSystem packer")
37+
.arg(Arg::with_name("source")
38+
.short("s")
39+
.long("source")
40+
.takes_value(true)
41+
.help("Executable source dir(with backslash)")
42+
)
43+
.arg(Arg::with_name("target")
44+
.short("t")
45+
.long("target")
46+
.takes_value(true)
47+
.help("Executable target dir(with backslash)")
48+
)
49+
.get_matches();
50+
let src_path = matches.value_of("source").unwrap();
51+
let target_path = matches.value_of("target").unwrap();
52+
println!("src_path = {}\ntarget_path = {}", src_path, target_path);
4053
let block_file = Arc::new(BlockFile(Mutex::new({
4154
let f = OpenOptions::new()
4255
.read(true)
4356
.write(true)
4457
.create(true)
45-
.open(format!("{}{}", TARGET_PATH, "fs.img"))?;
58+
.open(format!("{}{}", target_path, "fs.img"))?;
4659
f.set_len(8192 * 512).unwrap();
4760
f
4861
})));
@@ -53,7 +66,7 @@ fn easy_fs_pack() -> std::io::Result<()> {
5366
1,
5467
);
5568
let root_inode = Arc::new(EasyFileSystem::root_inode(&efs));
56-
let apps: Vec<_> = read_dir("../user/src/bin")
69+
let apps: Vec<_> = read_dir(src_path)
5770
.unwrap()
5871
.into_iter()
5972
.map(|dir_entry| {
@@ -64,7 +77,7 @@ fn easy_fs_pack() -> std::io::Result<()> {
6477
.collect();
6578
for app in apps {
6679
// load app data from host file system
67-
let mut host_file = File::open(format!("{}{}", TARGET_PATH, app)).unwrap();
80+
let mut host_file = File::open(format!("{}{}", target_path, app)).unwrap();
6881
let mut all_data: Vec<u8> = Vec::new();
6982
host_file.read_to_end(&mut all_data).unwrap();
7083
// create a file in easy-fs
@@ -79,22 +92,24 @@ fn easy_fs_pack() -> std::io::Result<()> {
7992
Ok(())
8093
}
8194

82-
/*
8395
#[test]
8496
fn efs_test() -> std::io::Result<()> {
85-
let block_file = Arc::new(BlockFile(Mutex::new(
86-
OpenOptions::new()
97+
let block_file = Arc::new(BlockFile(Mutex::new({
98+
let f = OpenOptions::new()
8799
.read(true)
88100
.write(true)
89-
.open("target/fs.img")?
90-
)));
101+
.create(true)
102+
.open("target/fs.img")?;
103+
f.set_len(8192 * 512).unwrap();
104+
f
105+
})));
91106
EasyFileSystem::create(
92107
block_file.clone(),
93108
4096,
94109
1,
95110
);
96111
let efs = EasyFileSystem::open(block_file.clone());
97-
let mut root_inode = EasyFileSystem::root_inode(&efs);
112+
let root_inode = EasyFileSystem::root_inode(&efs);
98113
root_inode.create("filea");
99114
root_inode.create("fileb");
100115
for name in root_inode.ls() {
@@ -146,5 +161,4 @@ fn efs_test() -> std::io::Result<()> {
146161
random_str_test((12 + 128) * BLOCK_SZ);
147162

148163
Ok(())
149-
}
150-
*/
164+
}

easy-fs/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,4 @@ edition = "2018"
88

99
[dependencies]
1010
spin = "0.7.0"
11-
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
12-
#rand = "0.8.0"
11+
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }

easy-fs/build.rs

Lines changed: 0 additions & 6 deletions
This file was deleted.

easy-fs/src/bitmap.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use alloc::sync::Arc;
2-
use super::BlockDevice;
3-
use super::Dirty;
4-
use super::BLOCK_SZ;
2+
use super::{
3+
BlockDevice,
4+
BLOCK_SZ,
5+
get_block_cache,
6+
};
57

68
type BitmapBlock = [u64; 64];
79

@@ -26,41 +28,45 @@ impl Bitmap {
2628
blocks,
2729
}
2830
}
31+
2932
pub fn alloc(&self, block_device: &Arc<dyn BlockDevice>) -> Option<usize> {
3033
for block_id in 0..self.blocks {
31-
let mut dirty_bitmap_block: Dirty<BitmapBlock> = Dirty::new(
34+
let pos = get_block_cache(
3235
block_id + self.start_block_id as usize,
33-
0,
34-
block_device.clone()
35-
);
36-
let bitmap_block = dirty_bitmap_block.get_mut();
37-
if let Some((bits64_pos, inner_pos)) = bitmap_block
38-
.iter()
39-
.enumerate()
40-
.find(|(_, bits64)| **bits64 != u64::MAX)
41-
.map(|(bits64_pos, bits64)| {
42-
(bits64_pos, bits64.trailing_ones() as usize)
43-
}) {
44-
// modify cache
45-
bitmap_block[bits64_pos] |= 1u64 << inner_pos;
46-
return Some(block_id * BLOCK_BITS + bits64_pos * 64 + inner_pos as usize);
47-
// after dirty is dropped, data will be written back automatically
36+
Arc::clone(block_device),
37+
).lock().modify(0, |bitmap_block: &mut BitmapBlock| {
38+
if let Some((bits64_pos, inner_pos)) = bitmap_block
39+
.iter()
40+
.enumerate()
41+
.find(|(_, bits64)| **bits64 != u64::MAX)
42+
.map(|(bits64_pos, bits64)| {
43+
(bits64_pos, bits64.trailing_ones() as usize)
44+
}) {
45+
// modify cache
46+
bitmap_block[bits64_pos] |= 1u64 << inner_pos;
47+
Some(block_id * BLOCK_BITS + bits64_pos * 64 + inner_pos as usize)
48+
} else {
49+
None
50+
}
51+
});
52+
if pos.is_some() {
53+
return pos;
4854
}
4955
}
5056
None
5157
}
58+
5259
pub fn dealloc(&self, block_device: &Arc<dyn BlockDevice>, bit: usize) {
5360
let (block_pos, bits64_pos, inner_pos) = decomposition(bit);
54-
let mut dirty_bitmap_block: Dirty<BitmapBlock> = Dirty::new(
61+
get_block_cache(
5562
block_pos + self.start_block_id,
56-
0,
57-
block_device.clone(),
58-
);
59-
dirty_bitmap_block.modify(|bitmap_block| {
63+
Arc::clone(block_device)
64+
).lock().modify(0, |bitmap_block: &mut BitmapBlock| {
6065
assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0);
6166
bitmap_block[bits64_pos] -= 1u64 << inner_pos;
6267
});
6368
}
69+
6470
pub fn maximum(&self) -> usize {
6571
self.blocks * BLOCK_BITS
6672
}

easy-fs/src/block_cache.rs

Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,128 @@
11
use super::{
2-
BlockDevice,
32
BLOCK_SZ,
3+
BlockDevice,
44
};
5-
use alloc::sync::{Arc, Weak};
6-
use alloc::collections::BTreeMap;
5+
use alloc::collections::VecDeque;
6+
use alloc::sync::Arc;
77
use lazy_static::*;
88
use spin::Mutex;
99

1010
pub struct BlockCache {
1111
cache: [u8; BLOCK_SZ],
1212
block_id: usize,
1313
block_device: Arc<dyn BlockDevice>,
14+
modified: bool,
1415
}
1516

1617
impl BlockCache {
17-
pub fn new(block_id: usize, block_device: Arc<dyn BlockDevice>) -> Self {
18+
/// Load a new BlockCache from disk.
19+
pub fn new(
20+
block_id: usize,
21+
block_device: Arc<dyn BlockDevice>
22+
) -> Self {
1823
let mut cache = [0u8; BLOCK_SZ];
1924
block_device.read_block(block_id, &mut cache);
2025
Self {
2126
cache,
2227
block_id,
2328
block_device,
29+
modified: false,
2430
}
2531
}
26-
pub fn start_addr(&self, offset: usize) -> usize {
32+
33+
fn addr_of_offset(&self, offset: usize) -> usize {
2734
&self.cache[offset] as *const _ as usize
2835
}
36+
37+
pub fn get_ref<T>(&self, offset: usize) -> &T where T: Sized {
38+
let type_size = core::mem::size_of::<T>();
39+
assert!(offset + type_size <= BLOCK_SZ);
40+
let addr = self.addr_of_offset(offset);
41+
unsafe { &*(addr as *const T) }
42+
}
43+
44+
pub fn get_mut<T>(&mut self, offset: usize) -> &mut T where T: Sized {
45+
let type_size = core::mem::size_of::<T>();
46+
assert!(offset + type_size <= BLOCK_SZ);
47+
self.modified = true;
48+
let addr = self.addr_of_offset(offset);
49+
unsafe { &mut *(addr as *mut T) }
50+
}
51+
52+
pub fn read<T, V>(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V {
53+
f(self.get_ref(offset))
54+
}
55+
56+
pub fn modify<T, V>(&mut self, offset:usize, f: impl FnOnce(&mut T) -> V) -> V {
57+
f(self.get_mut(offset))
58+
}
59+
60+
pub fn sync(&mut self) {
61+
if self.modified {
62+
self.modified = false;
63+
self.block_device.write_block(self.block_id, &self.cache);
64+
}
65+
}
2966
}
3067

3168
impl Drop for BlockCache {
3269
fn drop(&mut self) {
33-
// write back
34-
self.block_device.write_block(self.block_id, &self.cache);
35-
// invalid in block cache manager
36-
BLOCK_CACHE_MANAGER.lock().invalid(self.block_id);
70+
self.sync()
3771
}
3872
}
3973

40-
pub struct BlockCacheManager {
41-
map: BTreeMap<usize, Weak<BlockCache>>,
42-
}
74+
const BLOCK_CACHE_SIZE: usize = 16;
4375

44-
lazy_static! {
45-
static ref BLOCK_CACHE_MANAGER: Mutex<BlockCacheManager> = Mutex::new(
46-
BlockCacheManager::new()
47-
);
76+
pub struct BlockCacheManager {
77+
queue: VecDeque<(usize, Arc<Mutex<BlockCache>>)>,
4878
}
4979

5080
impl BlockCacheManager {
5181
pub fn new() -> Self {
52-
Self { map: BTreeMap::new() }
82+
Self { queue: VecDeque::new() }
5383
}
54-
pub fn get(
84+
85+
pub fn get_block_cache(
5586
&mut self,
5687
block_id: usize,
57-
block_device: Arc<dyn BlockDevice>
58-
) -> Arc<BlockCache> {
59-
if let Some(block_cache) = self.map.get(&block_id) {
60-
// return cloned
61-
block_cache.upgrade().unwrap().clone()
88+
block_device: Arc<dyn BlockDevice>,
89+
) -> Arc<Mutex<BlockCache>> {
90+
if let Some(pair) = self.queue
91+
.iter()
92+
.find(|pair| pair.0 == block_id) {
93+
Arc::clone(&pair.1)
6294
} else {
63-
// fetch from disk
64-
let block_cache = Arc::new(BlockCache::new(
65-
block_id,
66-
block_device.clone()
95+
// substitute
96+
if self.queue.len() == BLOCK_CACHE_SIZE {
97+
// from front to tail
98+
if let Some((idx, _)) = self.queue
99+
.iter()
100+
.enumerate()
101+
.find(|(_, pair)| Arc::strong_count(&pair.1) == 1) {
102+
self.queue.drain(idx..=idx);
103+
} else {
104+
panic!("Run out of BlockCache!");
105+
}
106+
}
107+
// load block into mem and push back
108+
let block_cache = Arc::new(Mutex::new(
109+
BlockCache::new(block_id, Arc::clone(&block_device))
67110
));
68-
self.map.insert(
69-
block_id,
70-
Arc::downgrade(&block_cache),
71-
);
72-
// return
111+
self.queue.push_back((block_id, Arc::clone(&block_cache)));
73112
block_cache
74113
}
75114
}
76-
pub fn invalid(&mut self, block_id: usize) {
77-
assert!(self.map.remove(&block_id).is_some());
78-
}
115+
}
116+
117+
lazy_static! {
118+
pub static ref BLOCK_CACHE_MANAGER: Mutex<BlockCacheManager> = Mutex::new(
119+
BlockCacheManager::new()
120+
);
79121
}
80122

81123
pub fn get_block_cache(
82124
block_id: usize,
83125
block_device: Arc<dyn BlockDevice>
84-
) -> Arc<BlockCache> {
85-
BLOCK_CACHE_MANAGER.lock().get(block_id, block_device)
126+
) -> Arc<Mutex<BlockCache>> {
127+
BLOCK_CACHE_MANAGER.lock().get_block_cache(block_id, block_device)
86128
}

0 commit comments

Comments
 (0)