summaryrefslogtreecommitdiff
path: root/ayafs-core/src/lib.rs
diff options
context:
space:
mode:
authorChuyan Zhang <me@zcy.moe>2023-11-30 12:01:11 -0800
committerChuyan Zhang <me@zcy.moe>2023-11-30 12:01:11 -0800
commitfd125947c9db0b33761414e65e919f73d9bf1815 (patch)
treec4c66d95ba85601427928aa7f23659590055d464 /ayafs-core/src/lib.rs
parent1eac97eea4ec0bcef0be061a2cba93a584355283 (diff)
downloadmyfs-fd125947c9db0b33761414e65e919f73d9bf1815.tar.gz
myfs-fd125947c9db0b33761414e65e919f73d9bf1815.zip
Refactor workspace
Diffstat (limited to 'ayafs-core/src/lib.rs')
-rw-r--r--ayafs-core/src/lib.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/ayafs-core/src/lib.rs b/ayafs-core/src/lib.rs
new file mode 100644
index 0000000..5ec118a
--- /dev/null
+++ b/ayafs-core/src/lib.rs
@@ -0,0 +1,140 @@
+pub mod block_device;
+pub mod disk;
+pub mod filesystem;
+pub mod memory;
+pub mod tests;
+pub mod utils;
+
+
+use indexmap::IndexMap;
+use log::debug;
+use lru::LruCache;
+use std::collections::HashMap;
+use std::ffi::OsString;
+use std::num::NonZeroUsize;
+use std::sync::atomic::AtomicU64;
+use std::sync::Arc;
+use std::time::Duration;
+
+use crate::disk::block::{DirectoryEntry, InodeBlock, SuperBlock};
+use crate::memory::cached_block::BlockCache;
+use block_device::{BlockDevice, BLOCK_SIZE};
+use disk::bitmap::Bitmap;
+use disk::block::DataBlock;
+use disk::inode::INODE_SIZE;
+use users::{get_current_gid, get_current_uid};
+
+const TTL: Duration = Duration::new(0, 0);
+const INODE_PER_BLOCK: usize = BLOCK_SIZE / INODE_SIZE;
+
+/// The design of MyFS is rather simple:
+/// +-------------------+
+/// | Super Block |
+/// +-------------------+
+/// | Inode Bitmap |
+/// +-------------------+
+/// | ... |
+/// +-------------------+
+/// | Data Block Bitmap |
+/// +-------------------+
+/// | ... |
+/// +-------------------+
+/// | Inode Block |
+/// +-------------------+
+/// | ... |
+/// +-------------------+
+/// | Data Block |
+/// +-------------------+
+/// With each block 4KiB, each Inode entry 128B
+
+#[repr(C)]
+pub struct AyaFS {
+ device: Arc<dyn BlockDevice>,
+ data_bitmap: Bitmap,
+ inode_bitmap: Bitmap,
+ inode_start_block: usize,
+ data_start_block: usize,
+
+ next_file_handle: AtomicU64,
+ // file descriptor -> (inode index, read, write)
+ file_handle_map: HashMap<u64, (usize, bool, bool)>,
+
+ // inode index -> (index aware) hashmap that maps dir entry name to inode index
+ dir_entry_map: LruCache<usize, IndexMap<OsString, DirectoryEntry>>,
+
+ cached_inodes: BlockCache<InodeBlock>,
+ cached_blocks: BlockCache<DataBlock>,
+
+ super_block: SuperBlock,
+}
+
+impl AyaFS {
+ pub fn new(device: Arc<dyn BlockDevice>, total_block_number: usize) -> Self {
+ let max_inode_number: usize = 16384; // TODO: remove hard-coded magic number
+ let inode_block_number = max_inode_number / INODE_PER_BLOCK; // == 128
+ let inode_bitmap_block_number = (inode_block_number + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ let blocks_remaining =
+ total_block_number - inode_block_number - inode_bitmap_block_number - 1;
+ // let number of data blocks be x, the remaining block number be C,
+ // the corresponding data bitmap length should be ceil(x / BLK_SIZE),
+ // thus we have BLK_SIZE * (C-1) / (BLK_SIZE+1) <= x <= BLK_SIZE * C / (BLK_SIZE+1)
+ // the difference of the two bounds is less than 1,
+ // meaning only 1 integer could be in between.
+ // Thus we have x = floor(BLK_SIZE * C / (BLK_SIZE + 1))
+ let data_block_number = BLOCK_SIZE * blocks_remaining / (BLOCK_SIZE + 1);
+ let data_bitmap_block_number = blocks_remaining - data_block_number;
+ debug!("data_bitmap_block_number: {}", data_bitmap_block_number);
+ debug!("inode_bitmap_block_number: {}", inode_bitmap_block_number);
+ debug!("inode_block_number: {}", inode_block_number);
+ debug!("data_block_number: {}", data_block_number);
+ debug!(
+ "sum: {}",
+ 1 + data_bitmap_block_number
+ + inode_bitmap_block_number
+ + inode_block_number
+ + data_block_number
+ );
+
+ let super_block = SuperBlock::new(
+ data_bitmap_block_number,
+ inode_bitmap_block_number,
+ inode_block_number,
+ data_block_number,
+ );
+
+ let mut data_bitmap = Bitmap::new(1, data_bitmap_block_number, device.clone());
+ let _ = data_bitmap.allocate().unwrap(); // data block 0 is not usable
+ let mut inode_bitmap = Bitmap::new(
+ data_bitmap_block_number + 1,
+ inode_bitmap_block_number,
+ device.clone(),
+ );
+ let _ = inode_bitmap.allocate().unwrap(); // inode block 0 is not usable
+
+ let mut fs = Self {
+ device: device.clone(),
+ data_bitmap,
+ inode_bitmap,
+ inode_start_block: data_bitmap_block_number + inode_bitmap_block_number + 1,
+ data_start_block: data_bitmap_block_number
+ + inode_bitmap_block_number
+ + inode_block_number
+ + 1,
+
+ next_file_handle: AtomicU64::new(3), // 0,1,2 are stdin, stdout and stderr
+ file_handle_map: HashMap::new(),
+
+ dir_entry_map: LruCache::new(NonZeroUsize::new(1024).unwrap()),
+
+ cached_inodes: BlockCache::new(device.clone(), 1024),
+ cached_blocks: BlockCache::new(device.clone(), 8192),
+
+ super_block,
+ };
+
+ fs.create_directory(0o755, get_current_uid(), get_current_gid(), 0, None);
+
+ fs
+ }
+}