summaryrefslogtreecommitdiff
path: root/src/disk
diff options
context:
space:
mode:
authorChuyan Zhang <me@zcy.moe>2023-11-17 11:40:33 -0800
committerChuyan Zhang <me@zcy.moe>2023-11-17 11:40:33 -0800
commit95d8d84eef645b52d92fd3fb8fdea7aed1f6d474 (patch)
treeab65714726edeec94fd35f424e21a1f77da71b3c /src/disk
parent7a748cadbb2e2ce8c0e045cb8fbd77ccbd47459f (diff)
downloadmyfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.tar.gz
myfs-95d8d84eef645b52d92fd3fb8fdea7aed1f6d474.zip
Layer 1 incomplete
Diffstat (limited to 'src/disk')
-rw-r--r--src/disk/bitmap.rs13
-rw-r--r--src/disk/data_block.rs94
-rw-r--r--src/disk/inode.rs184
-rw-r--r--src/disk/mod.rs4
4 files changed, 205 insertions, 90 deletions
diff --git a/src/disk/bitmap.rs b/src/disk/bitmap.rs
index a5a9cc4..d5a8fe9 100644
--- a/src/disk/bitmap.rs
+++ b/src/disk/bitmap.rs
@@ -19,20 +19,25 @@ impl Bitmap {
dirty_blocks: Vec::new(),
}
}
- pub fn allocate(&mut self) -> usize {
+ pub fn allocate(&mut self) -> Option<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;
+ return Some(i * 8 + leading_ones as usize);
}
}
- panic!("No more space for allocation!")
+ None
+ // panic!("No more space for allocation!")
}
pub fn query(&self, index: usize) -> bool {
- self.data[index / 8] & ((1 << (7 - index % 8)) as u8) != 0
+ if index == 0 {
+ false
+ } else {
+ self.data[index / 8] & ((1 << (7 - index % 8)) as u8) != 0
+ }
}
fn write_back(&mut self) {
diff --git a/src/disk/data_block.rs b/src/disk/data_block.rs
new file mode 100644
index 0000000..2160b91
--- /dev/null
+++ b/src/disk/data_block.rs
@@ -0,0 +1,94 @@
+pub trait Block: Default {}
+
+#[derive(Default)]
+pub struct DataBlock([u8; 4096]);
+impl Block for DataBlock {}
+
+const FULL_MAP: u32 = 0b111_111_111_111_111;
+
+#[derive(Default)]
+pub struct DirectoryBlock {
+ entries: [[u8; 256]; 15],
+ inode_ids: [usize; 15],
+ occupancy_map: u32,
+ reserved: [u8; 132],
+}
+
+impl Block for DirectoryBlock {}
+
+impl DirectoryBlock {
+ fn vacant(&self) -> bool {
+ self.occupancy_map & FULL_MAP != FULL_MAP
+ }
+
+ fn first_free(&self) -> Option<usize> {
+ todo!()
+ }
+
+ fn mark_busy(&mut self, entry_id: usize) {
+ todo!()
+ }
+
+ /// 需要判断 entry_name.len() <= 255
+ pub fn write_entry(&mut self, entry_name: &[u8], entry_inode_id: usize) -> Option<usize> {
+ if let Some(entry_id) = self.first_free() {
+ self.mark_busy(entry_id);
+ self.entries[entry_id].copy_from_slice(entry_name);
+ self.inode_ids[entry_id] = entry_inode_id;
+ Some(entry_id)
+ } else {
+ None
+ }
+ }
+}
+
+#[derive(Default)]
+pub struct IndirectBlock {
+ pub entries: [u32; 1024],
+}
+
+impl Block for IndirectBlock {}
+
+impl IndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
+
+#[derive(Default)]
+pub struct DoubleIndirectBlock {
+ pub indirect: [u32; 1024],
+}
+
+impl Block for DoubleIndirectBlock {}
+
+impl DoubleIndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
+
+#[derive(Default)]
+pub struct TripleIndirectBlock {
+ pub double_indirect: [u32; 1024],
+}
+
+impl Block for TripleIndirectBlock {}
+
+impl TripleIndirectBlock {
+ pub fn full(&self) -> bool {
+ todo!()
+ }
+
+ pub fn allocate(&mut self) -> Option<usize> {
+ todo!()
+ }
+}
diff --git a/src/disk/inode.rs b/src/disk/inode.rs
index f38508a..6adc75d 100644
--- a/src/disk/inode.rs
+++ b/src/disk/inode.rs
@@ -42,111 +42,125 @@ pub struct Inode {
mode: InodeMode,
uid: u32,
size: u32,
- atime: u32, // time in seconds
- ctime: u32,
- mtime: u32,
- dtime: u32,
+ atime: u32, // access time, in seconds
+ ctime: u32, // change time, in seconds
+ mtime: u32, // modify time, in seconds
+ crtime: u32, // create time, in seconds
gid: u32,
- n_links: u16,
- n_blocks: u32,
+ pub n_links: u16,
+ pub 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,
+ pub direct: [u32; DIRECT_NUMBER],
+ pub single_indirect: u32,
+ pub double_indirect: u32,
+ pub triple_indirect: u32,
generation: u32,
file_acl: u32,
dir_acl: u32, // TODO do we have to implement ACL......?
}
impl Inode {
- pub fn directory() -> Self {
+ fn new(
+ mode: InodeMode,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
Self {
- mode: InodeMode::IFDIR
- | InodeMode::IRUSR
- | InodeMode::IWUSR
- | InodeMode::IXUSR
- | InodeMode::IRGRP
- | InodeMode::IXGRP
- | InodeMode::IROTH
- | InodeMode::IXOTH,
- // Directory, 755 permissions
- uid: 0,
+ mode,
+ uid,
size: 0,
- atime: 0,
- ctime: 0,
- mtime: 0,
- dtime: 0,
- gid: 0,
+ atime: time,
+ ctime: time,
+ mtime: time,
+ crtime: time,
+ gid,
n_links: 0,
n_blocks: 0,
- flags: 0,
+ flags,
direct: [0; DIRECT_NUMBER],
single_indirect: 0,
double_indirect: 0,
triple_indirect: 0,
- generation: 0,
- file_acl: 0,
- dir_acl: 0,
+ generation,
+ file_acl,
+ dir_acl,
}
}
- 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,
- }
+ pub fn make_inode(
+ permissions: u16,
+ mode: InodeMode,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | mode,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
}
-}
-//
-// #[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 fn directory(
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | InodeMode::IFDIR,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
+ }
+ pub fn file(
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | InodeMode::IFREG,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
+ }
+
+ pub fn empty() -> Self {
+ Self::new(InodeMode(0), 0, 0, 0, 0, 0, 0, 0)
+ }
+}
pub const INODE_SIZE: usize = std::mem::size_of::<Inode>();
diff --git a/src/disk/mod.rs b/src/disk/mod.rs
index e4e4216..404c6ab 100644
--- a/src/disk/mod.rs
+++ b/src/disk/mod.rs
@@ -1,2 +1,4 @@
-pub mod inode;
pub mod bitmap;
+pub mod inode;
+
+pub mod data_block;