From 7a748cadbb2e2ce8c0e045cb8fbd77ccbd47459f Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Tue, 17 Oct 2023 23:07:21 -0700 Subject: initial commit --- src/disk/bitmap.rs | 49 +++++++++++++++++ src/disk/inode.rs | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/disk/mod.rs | 2 + 3 files changed, 203 insertions(+) create mode 100644 src/disk/bitmap.rs create mode 100644 src/disk/inode.rs create mode 100644 src/disk/mod.rs (limited to 'src/disk') diff --git a/src/disk/bitmap.rs b/src/disk/bitmap.rs new file mode 100644 index 0000000..a5a9cc4 --- /dev/null +++ b/src/disk/bitmap.rs @@ -0,0 +1,49 @@ +use crate::block_device::{BlockDevice, BLOCK_SIZE}; +use std::sync::Arc; + +pub struct Bitmap { + pub starting_block: usize, + pub length: usize, + pub device: Arc, + pub data: Vec, + pub dirty_blocks: Vec, +} + +impl Bitmap { + pub fn new(starting_block: usize, length: usize, device: Arc) -> Self { + Self { + starting_block, + length, + device, + data: vec![0u8; length * BLOCK_SIZE], + dirty_blocks: Vec::new(), + } + } + pub fn allocate(&mut self) -> usize { + for (i, byte) in self.data.iter_mut().enumerate() { + let leading_ones = byte.leading_ones(); + if leading_ones != 8 { + *byte |= (1 << (7 - leading_ones)) as u8; + self.dirty_blocks.push(i / BLOCK_SIZE); + return i * 8 + leading_ones as usize; + } + } + panic!("No more space for allocation!") + } + + pub fn query(&self, index: usize) -> bool { + self.data[index / 8] & ((1 << (7 - index % 8)) as u8) != 0 + } + + fn write_back(&mut self) { + for block_index_offset in self.dirty_blocks.iter() { + let buffer_front_index = BLOCK_SIZE * block_index_offset; + let buffer_back_index = BLOCK_SIZE * (block_index_offset + 1); + self.device.write( + self.starting_block + block_index_offset, + &self.data[buffer_front_index..buffer_back_index], + ); + } + self.dirty_blocks = Vec::new(); + } +} diff --git a/src/disk/inode.rs b/src/disk/inode.rs new file mode 100644 index 0000000..f38508a --- /dev/null +++ b/src/disk/inode.rs @@ -0,0 +1,152 @@ +use bitflags::bitflags; + +const DIRECT_NUMBER: usize = 15; + +#[derive(Debug)] +pub struct InodeMode(u16); + +bitflags! { + impl InodeMode: u16 { + const IXOTH = 0x0001; + const IWOTH = 0x0002; + const IROTH = 0x0004; + const IXGRP = 0x0008; + const IWGRP = 0x0010; + const IRGRP = 0x0020; + const IXUSR = 0x0040; + const IWUSR = 0x0080; + const IRUSR = 0x0100; + const ISVTX = 0x0200; + const ISGID = 0x0400; + const ISUID = 0x0800; + // These are mutually-exclusive: + const IFIFO = 0x1000; + const IFCHR = 0x2000; + const IFDIR = 0x4000; + const IFBLK = 0x6000; + const IFREG = 0x8000; + const IFLNK = 0xA000; + const IFSOCK = 0xC000; + } +} + +/// Pretty much the same with ext2, with minor changes: +/// - removed OS dependent attributes (osd1 & osd2) +/// - removed i_faddr since fragmentation is not supported +/// - changed uid and gid from u16 to u32 +/// - added more direct blocks for a total size of 128 bytes +/// TODO: do we need to extend time precision? +#[repr(C)] +#[derive(Debug)] +pub struct Inode { + mode: InodeMode, + uid: u32, + size: u32, + atime: u32, // time in seconds + ctime: u32, + mtime: u32, + dtime: u32, + gid: u32, + n_links: u16, + n_blocks: u32, + flags: u32, // TODO: do we actually need this? maybe just return 0 + direct: [u32; DIRECT_NUMBER], + single_indirect: u32, + double_indirect: u32, + triple_indirect: u32, + generation: u32, + file_acl: u32, + dir_acl: u32, // TODO do we have to implement ACL......? +} + +impl Inode { + pub fn directory() -> Self { + Self { + mode: InodeMode::IFDIR + | InodeMode::IRUSR + | InodeMode::IWUSR + | InodeMode::IXUSR + | InodeMode::IRGRP + | InodeMode::IXGRP + | InodeMode::IROTH + | InodeMode::IXOTH, + // Directory, 755 permissions + uid: 0, + size: 0, + atime: 0, + ctime: 0, + mtime: 0, + dtime: 0, + gid: 0, + n_links: 0, + n_blocks: 0, + flags: 0, + direct: [0; DIRECT_NUMBER], + single_indirect: 0, + double_indirect: 0, + triple_indirect: 0, + generation: 0, + file_acl: 0, + dir_acl: 0, + } + } + + pub fn file() -> Self { + Self { + mode: InodeMode::IFREG + | InodeMode::IRUSR + | InodeMode::IWUSR + | InodeMode::IXUSR + | InodeMode::IRGRP + | InodeMode::IXGRP + | InodeMode::IROTH + | InodeMode::IXOTH, + // RegularFile, 755 permissions + uid: 0, + size: 0, + atime: 0, + ctime: 0, + mtime: 0, + dtime: 0, + gid: 0, + n_links: 0, + n_blocks: 0, + flags: 0, + direct: [0; DIRECT_NUMBER], + single_indirect: 0, + double_indirect: 0, + triple_indirect: 0, + generation: 0, + file_acl: 0, + dir_acl: 0, + } + } +} + +// +// #[repr(C)] +// #[derive(Debug, Default)] +// pub struct FileInode { +// file_size: u32, +// direct_blocks: [u32; DIRECT_NUMBER], +// indirect_block: u32, +// doubly_indirect_block: u32, +// } // sizeof(FileInode) == 124 bytes +// +// #[repr(C)] +// #[derive(Debug, Default)] +// pub struct DirectoryInode { +// child_number: u32, +// direct_blocks: [u32; DIRECT_NUMBER], +// indirect_block: u32, +// doubly_indirect_block: u32, +// } // sizeof(FileInode) == 124 bytes +// +// #[repr(C)] +// #[derive(Debug)] +// pub enum Inode { +// File(FileInode), +// Directory(DirectoryInode), +// } // sizeof(Inode) == 128 bytes + +pub const INODE_SIZE: usize = std::mem::size_of::(); diff --git a/src/disk/mod.rs b/src/disk/mod.rs new file mode 100644 index 0000000..e4e4216 --- /dev/null +++ b/src/disk/mod.rs @@ -0,0 +1,2 @@ +pub mod inode; +pub mod bitmap; -- cgit v1.2.3-70-g09d2