Skip to content

Commit e1fdaf7

Browse files
committed
Init the ch6
1 parent c606328 commit e1fdaf7

38 files changed

+1914
-207
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ easy-fs-fuse/target/*
1515
tools/
1616
pushall.sh
1717
*.bak
18-
1918
ci-user/
20-
os/vendor/
2119
user/
20+
os/vendor/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ build_docker:
88
docker build -t ${DOCKER_NAME} .
99

1010
fmt:
11-
cd os ; cargo fmt; cd ..
11+
cd easy-fs; cargo fmt; cd ../easy-fs-fuse cargo fmt; cd ../os ; cargo fmt; cd ../user; cargo fmt; cd ..
1212

easy-fs-fuse/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea/
2+
target/
3+
Cargo.lock

easy-fs-fuse/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "easy-fs-fuse"
3+
version = "0.1.0"
4+
authors = ["Yifan Wu <shinbokuow@163.com>"]
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"
13+
14+
# [features]
15+
# board_qemu = []
16+
# board_k210 = []

easy-fs-fuse/src/main.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use clap::{App, Arg};
2+
use easy_fs::{BlockDevice, EasyFileSystem};
3+
use std::fs::{read_dir, File, OpenOptions};
4+
use std::io::{Read, Seek, SeekFrom, Write};
5+
use std::sync::Arc;
6+
use std::sync::Mutex;
7+
8+
const BLOCK_SZ: usize = 512;
9+
10+
struct BlockFile(Mutex<File>);
11+
12+
impl BlockDevice for BlockFile {
13+
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
14+
let mut file = self.0.lock().unwrap();
15+
file.seek(SeekFrom::Start((block_id * BLOCK_SZ) as u64))
16+
.expect("Error when seeking!");
17+
assert_eq!(file.read(buf).unwrap(), BLOCK_SZ, "Not a complete block!");
18+
}
19+
20+
fn write_block(&self, block_id: usize, buf: &[u8]) {
21+
let mut file = self.0.lock().unwrap();
22+
file.seek(SeekFrom::Start((block_id * BLOCK_SZ) as u64))
23+
.expect("Error when seeking!");
24+
assert_eq!(file.write(buf).unwrap(), BLOCK_SZ, "Not a complete block!");
25+
}
26+
}
27+
28+
fn main() {
29+
easy_fs_pack().expect("Error when packing easy-fs!");
30+
}
31+
32+
fn easy_fs_pack() -> std::io::Result<()> {
33+
let matches = App::new("EasyFileSystem packer")
34+
.arg(
35+
Arg::with_name("source")
36+
.short("s")
37+
.long("source")
38+
.takes_value(true)
39+
.help("Executable source dir(with backslash)"),
40+
)
41+
.arg(
42+
Arg::with_name("target")
43+
.short("t")
44+
.long("target")
45+
.takes_value(true)
46+
.help("Executable target dir(with backslash)"),
47+
)
48+
.get_matches();
49+
let src_path = matches.value_of("source").unwrap();
50+
let target_path = matches.value_of("target").unwrap();
51+
println!("src_path = {}\ntarget_path = {}", src_path, target_path);
52+
let block_file = Arc::new(BlockFile(Mutex::new({
53+
let f = OpenOptions::new()
54+
.read(true)
55+
.write(true)
56+
.create(true)
57+
.open(format!("{}{}", target_path, "fs.img"))?;
58+
f.set_len(16 * 2048 * 512).unwrap();
59+
f
60+
})));
61+
// 16MiB, at most 4095 files
62+
let efs = EasyFileSystem::create(block_file, 16 * 2048, 1);
63+
let root_inode = Arc::new(EasyFileSystem::root_inode(&efs));
64+
let apps: Vec<_> = read_dir(src_path)
65+
.unwrap()
66+
.into_iter()
67+
.map(|dir_entry| {
68+
let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap();
69+
name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len());
70+
name_with_ext
71+
})
72+
.collect();
73+
for app in apps {
74+
// load app data from host file system
75+
let mut host_file = File::open(format!("{}{}", target_path, app)).unwrap();
76+
let mut all_data: Vec<u8> = Vec::new();
77+
host_file.read_to_end(&mut all_data).unwrap();
78+
// create a file in easy-fs
79+
let inode = root_inode.create(app.as_str()).unwrap();
80+
// write data to easy-fs
81+
inode.write_at(0, all_data.as_slice());
82+
}
83+
// list apps
84+
// for app in root_inode.ls() {
85+
// println!("{}", app);
86+
// }
87+
Ok(())
88+
}
89+
90+
#[test]
91+
fn efs_test() -> std::io::Result<()> {
92+
let block_file = Arc::new(BlockFile(Mutex::new({
93+
let f = OpenOptions::new()
94+
.read(true)
95+
.write(true)
96+
.create(true)
97+
.open("target/fs.img")?;
98+
f.set_len(8192 * 512).unwrap();
99+
f
100+
})));
101+
EasyFileSystem::create(block_file.clone(), 4096, 1);
102+
let efs = EasyFileSystem::open(block_file.clone());
103+
let root_inode = EasyFileSystem::root_inode(&efs);
104+
root_inode.create("filea");
105+
root_inode.create("fileb");
106+
for name in root_inode.ls() {
107+
println!("{}", name);
108+
}
109+
let filea = root_inode.find("filea").unwrap();
110+
let greet_str = "Hello, world!";
111+
filea.write_at(0, greet_str.as_bytes());
112+
//let mut buffer = [0u8; 512];
113+
let mut buffer = [0u8; 233];
114+
let len = filea.read_at(0, &mut buffer);
115+
assert_eq!(greet_str, core::str::from_utf8(&buffer[..len]).unwrap(),);
116+
117+
let mut random_str_test = |len: usize| {
118+
filea.clear();
119+
assert_eq!(filea.read_at(0, &mut buffer), 0,);
120+
let mut str = String::new();
121+
use rand;
122+
// random digit
123+
for _ in 0..len {
124+
str.push(char::from('0' as u8 + rand::random::<u8>() % 10));
125+
}
126+
filea.write_at(0, str.as_bytes());
127+
let mut read_buffer = [0u8; 127];
128+
let mut offset = 0usize;
129+
let mut read_str = String::new();
130+
loop {
131+
let len = filea.read_at(offset, &mut read_buffer);
132+
if len == 0 {
133+
break;
134+
}
135+
offset += len;
136+
read_str.push_str(core::str::from_utf8(&read_buffer[..len]).unwrap());
137+
}
138+
assert_eq!(str, read_str);
139+
};
140+
141+
random_str_test(4 * BLOCK_SZ);
142+
random_str_test(8 * BLOCK_SZ + BLOCK_SZ / 2);
143+
random_str_test(100 * BLOCK_SZ);
144+
random_str_test(70 * BLOCK_SZ + BLOCK_SZ / 7);
145+
random_str_test((12 + 128) * BLOCK_SZ);
146+
random_str_test(400 * BLOCK_SZ);
147+
random_str_test(1000 * BLOCK_SZ);
148+
random_str_test(2000 * BLOCK_SZ);
149+
150+
Ok(())
151+
}

easy-fs/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea/
2+
target/
3+
Cargo.lock

easy-fs/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "easy-fs"
3+
version = "0.1.0"
4+
authors = ["Yifan Wu <shinbokuow@163.com>"]
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+
spin = "0.7.0"
11+
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
12+
13+
[profile.release]
14+
debug = true
15+
16+
[features]
17+
board_qemu = []
18+
board_k210 = []

easy-fs/src/bitmap.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use super::{get_block_cache, BlockDevice, BLOCK_SZ};
2+
use alloc::sync::Arc;
3+
/// A bitmap block
4+
type BitmapBlock = [u64; 64];
5+
/// Number of bits in a block
6+
const BLOCK_BITS: usize = BLOCK_SZ * 8;
7+
/// A bitmap
8+
pub struct Bitmap {
9+
start_block_id: usize,
10+
blocks: usize,
11+
}
12+
13+
/// Decompose bits into (block_pos, bits64_pos, inner_pos)
14+
fn decomposition(mut bit: usize) -> (usize, usize, usize) {
15+
let block_pos = bit / BLOCK_BITS;
16+
bit %= BLOCK_BITS;
17+
(block_pos, bit / 64, bit % 64)
18+
}
19+
20+
impl Bitmap {
21+
/// A new bitmap from start block id and number of blocks
22+
pub fn new(start_block_id: usize, blocks: usize) -> Self {
23+
Self {
24+
start_block_id,
25+
blocks,
26+
}
27+
}
28+
/// Allocate a new block from a block device
29+
pub fn alloc(&self, block_device: &Arc<dyn BlockDevice>) -> Option<usize> {
30+
for block_id in 0..self.blocks {
31+
let pos = get_block_cache(
32+
block_id + self.start_block_id as usize,
33+
Arc::clone(block_device),
34+
)
35+
.lock()
36+
.modify(0, |bitmap_block: &mut BitmapBlock| {
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)| (bits64_pos, bits64.trailing_ones() as usize))
42+
{
43+
// modify cache
44+
bitmap_block[bits64_pos] |= 1u64 << inner_pos;
45+
Some(block_id * BLOCK_BITS + bits64_pos * 64 + inner_pos as usize)
46+
} else {
47+
None
48+
}
49+
});
50+
if pos.is_some() {
51+
return pos;
52+
}
53+
}
54+
None
55+
}
56+
/// Deallocate a block
57+
pub fn dealloc(&self, block_device: &Arc<dyn BlockDevice>, bit: usize) {
58+
let (block_pos, bits64_pos, inner_pos) = decomposition(bit);
59+
get_block_cache(block_pos + self.start_block_id, Arc::clone(block_device))
60+
.lock()
61+
.modify(0, |bitmap_block: &mut BitmapBlock| {
62+
assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0);
63+
bitmap_block[bits64_pos] -= 1u64 << inner_pos;
64+
});
65+
}
66+
/// Get the max number of allocatable blocks
67+
pub fn maximum(&self) -> usize {
68+
self.blocks * BLOCK_BITS
69+
}
70+
}

0 commit comments

Comments
 (0)