1use super::{
2 block_cache_sync_all, get_block_cache, Bitmap, BlockDevice, DiskInode, DiskInodeType, Inode,
3 SuperBlock,
4};
5use crate::BLOCK_SZ;
6use alloc::sync::Arc;
7use spin::Mutex;
8pub struct EasyFileSystem {
10 pub block_device: Arc<dyn BlockDevice>,
12 pub inode_bitmap: Bitmap,
14 pub data_bitmap: Bitmap,
16 inode_area_start_block: u32,
17 data_area_start_block: u32,
18}
19
20type DataBlock = [u8; BLOCK_SZ];
21impl EasyFileSystem {
23 pub fn create(
25 block_device: Arc<dyn BlockDevice>,
26 total_blocks: u32,
27 inode_bitmap_blocks: u32,
28 ) -> Arc<Mutex<Self>> {
29 let inode_bitmap = Bitmap::new(1, inode_bitmap_blocks as usize);
31 let inode_num = inode_bitmap.maximum();
32 let inode_area_blocks =
33 (inode_num * core::mem::size_of::<DiskInode>()).div_ceil(BLOCK_SZ) as u32;
34 let inode_total_blocks = inode_bitmap_blocks + inode_area_blocks;
35 let data_total_blocks = total_blocks - 1 - inode_total_blocks;
36 let data_bitmap_blocks = data_total_blocks.div_ceil(4097);
37 let data_area_blocks = data_total_blocks - data_bitmap_blocks;
38 let data_bitmap = Bitmap::new(
39 (1 + inode_bitmap_blocks + inode_area_blocks) as usize,
40 data_bitmap_blocks as usize,
41 );
42 let mut efs = Self {
43 block_device: Arc::clone(&block_device),
44 inode_bitmap,
45 data_bitmap,
46 inode_area_start_block: 1 + inode_bitmap_blocks,
47 data_area_start_block: 1 + inode_total_blocks + data_bitmap_blocks,
48 };
49 for i in 0..total_blocks {
51 get_block_cache(i as usize, Arc::clone(&block_device))
52 .lock()
53 .modify(0, |data_block: &mut DataBlock| {
54 for byte in data_block.iter_mut() {
55 *byte = 0;
56 }
57 });
58 }
59 get_block_cache(0, Arc::clone(&block_device)).lock().modify(
61 0,
62 |super_block: &mut SuperBlock| {
63 super_block.initialize(
64 total_blocks,
65 inode_bitmap_blocks,
66 inode_area_blocks,
67 data_bitmap_blocks,
68 data_area_blocks,
69 );
70 },
71 );
72 assert_eq!(efs.alloc_inode(), 0);
74 let (root_inode_block_id, root_inode_offset) = efs.get_disk_inode_pos(0);
75 get_block_cache(root_inode_block_id as usize, Arc::clone(&block_device))
76 .lock()
77 .modify(root_inode_offset, |disk_inode: &mut DiskInode| {
78 disk_inode.initialize(DiskInodeType::Directory);
79 });
80 block_cache_sync_all();
81 Arc::new(Mutex::new(efs))
82 }
83 pub fn open(block_device: Arc<dyn BlockDevice>) -> Arc<Mutex<Self>> {
85 get_block_cache(0, Arc::clone(&block_device))
87 .lock()
88 .read(0, |super_block: &SuperBlock| {
89 assert!(super_block.is_valid(), "Error loading EFS!");
90 let inode_total_blocks =
91 super_block.inode_bitmap_blocks + super_block.inode_area_blocks;
92 let efs = Self {
93 block_device,
94 inode_bitmap: Bitmap::new(1, super_block.inode_bitmap_blocks as usize),
95 data_bitmap: Bitmap::new(
96 (1 + inode_total_blocks) as usize,
97 super_block.data_bitmap_blocks as usize,
98 ),
99 inode_area_start_block: 1 + super_block.inode_bitmap_blocks,
100 data_area_start_block: 1 + inode_total_blocks + super_block.data_bitmap_blocks,
101 };
102 Arc::new(Mutex::new(efs))
103 })
104 }
105 pub fn root_inode(efs: &Arc<Mutex<Self>>) -> Inode {
107 let block_device = Arc::clone(&efs.lock().block_device);
108 let (block_id, block_offset) = efs.lock().get_disk_inode_pos(0);
110 Inode::new(block_id, block_offset, Arc::clone(efs), block_device)
112 }
113 pub fn get_disk_inode_pos(&self, inode_id: u32) -> (u32, usize) {
115 let inode_size = core::mem::size_of::<DiskInode>();
116 let inodes_per_block = (BLOCK_SZ / inode_size) as u32;
117 let block_id = self.inode_area_start_block + inode_id / inodes_per_block;
118 (
119 block_id,
120 (inode_id % inodes_per_block) as usize * inode_size,
121 )
122 }
123 pub fn get_data_block_id(&self, data_block_id: u32) -> u32 {
125 self.data_area_start_block + data_block_id
126 }
127 pub fn alloc_inode(&mut self) -> u32 {
129 self.inode_bitmap.alloc(&self.block_device).unwrap() as u32
130 }
131
132 pub fn alloc_data(&mut self) -> u32 {
134 self.data_bitmap.alloc(&self.block_device).unwrap() as u32 + self.data_area_start_block
135 }
136 pub fn dealloc_data(&mut self, block_id: u32) {
138 get_block_cache(block_id as usize, Arc::clone(&self.block_device))
139 .lock()
140 .modify(0, |data_block: &mut DataBlock| {
141 data_block.iter_mut().for_each(|p| {
142 *p = 0;
143 })
144 });
145 self.data_bitmap.dealloc(
146 &self.block_device,
147 (block_id - self.data_area_start_block) as usize,
148 )
149 }
150}