Browse Source

feat: optional cache feature

liujingx 9 months ago
parent
commit
78c6eba8e3
10 changed files with 86 additions and 16 deletions
  1. 4 1
      Cargo.toml
  2. 1 1
      ext4_fuse/Cargo.toml
  3. 4 0
      ext4_fuse/src/fuse_fs.rs
  4. 0 1
      ext4_test/src/main.rs
  5. 14 5
      src/ext4/low_level.rs
  6. 8 0
      src/ext4/mod.rs
  7. 17 3
      src/ext4/rw.rs
  8. 32 2
      src/ext4_defs/cache.rs
  9. 6 2
      src/ext4_defs/mod.rs
  10. 0 1
      src/prelude.rs

+ 4 - 1
Cargo.toml

@@ -6,4 +6,7 @@ edition = "2021"
 [dependencies]
 bitflags = "2.2.1"
 log = "0.4"
-axsync = { git = "https://github.com/Starry-OS/axsync.git" }
+axsync = { git = "https://github.com/Starry-OS/axsync.git", optional = true }
+
+[features]
+block_cache = ["dep:axsync"]

+ 1 - 1
ext4_fuse/Cargo.toml

@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 fuser = "0.13"
-another_ext4 = { path = ".." }
+another_ext4 = { path = "..", features = [] }
 simple_logger = "4.3"
 log = "0.4"
 clap = { version = "4.5.6", features = ["derive"] }

+ 4 - 0
ext4_fuse/src/fuse_fs.rs

@@ -93,6 +93,10 @@ impl<T: 'static> StateExt4FuseFs<T> {
 }
 
 impl<T: 'static> Filesystem for StateExt4FuseFs<T> {
+    fn destroy(&mut self) {
+        self.fs.flush_all();
+    }
+
     fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
         match self.fs.lookup(parent as u32, name.to_str().unwrap()) {
             Ok(inode_id) => reply.entry(&get_ttl(), &self.get_attr(inode_id).unwrap(), 0),

+ 0 - 1
ext4_test/src/main.rs

@@ -165,7 +165,6 @@ fn main() {
     println!("large read write test done");
     remove_file_test(&mut ext4);
     println!("remove file test done");
-    log::set_max_level(log::LevelFilter::Trace);
     xattr_test(&mut ext4);
     println!("xattr test done");
 }

+ 14 - 5
src/ext4/low_level.rs

@@ -412,7 +412,6 @@ impl Ext4 {
             return_error!(ErrCode::ENOTDIR, "Inode {} is not a directory", parent.id);
         }
         self.dir_find_entry(&parent, name)
-            .map(|entry| entry)
     }
 
     /// List all directory entries in a directory.
@@ -562,13 +561,13 @@ impl Ext4 {
     }
 
     /// List extended attributes of a file.
-    /// 
+    ///
     /// # Params
-    /// 
+    ///
     /// * `inode` - the inode of the file
-    /// 
+    ///
     /// # Returns
-    /// 
+    ///
     /// A list of extended attributes of the file.
     pub fn listxattr(&self, inode: InodeId) -> Result<Vec<String>> {
         let inode_ref = self.read_inode(inode);
@@ -579,4 +578,14 @@ impl Ext4 {
         let xattr_block = XattrBlock::new(self.read_block(xattr_block_id));
         Ok(xattr_block.list())
     }
+
+    /// Flush all dirty blocks in cache to disk.
+    ///
+    /// This always succeeds.
+    pub fn flush_all(&self) {
+        #[cfg(feature = "block_cache")]
+        {
+            self.block_cache.flush_all();
+        }
+    }
 }

+ 8 - 0
src/ext4/mod.rs

@@ -12,8 +12,12 @@ mod link;
 mod low_level;
 mod rw;
 
+/// The Ext4 filesystem implementation.
 pub struct Ext4 {
+    #[cfg(feature = "block_cache")]
     block_cache: BlockCache,
+    #[cfg(not(feature = "block_cache"))]
+    block_device: Arc<dyn BlockDevice>,
 }
 
 impl Ext4 {
@@ -42,9 +46,13 @@ impl Ext4 {
         }
         // Create Ext4 instance
         Ok(Self {
+            #[cfg(feature = "block_cache")]
             block_cache: BlockCache::new(block_device),
+            #[cfg(not(feature = "block_cache"))]
+            block_device,
         })
     }
+    
     /// Initializes the root directory.
     pub fn init(&mut self) -> Result<()> {
         // Create root directory

+ 17 - 3
src/ext4/rw.rs

@@ -1,17 +1,31 @@
+use super::Ext4;
 use crate::constants::*;
 use crate::ext4_defs::*;
 use crate::prelude::*;
-use super::Ext4;
 
 impl Ext4 {
     /// Read a block from block device
     pub(super) fn read_block(&self, block_id: PBlockId) -> Block {
-        self.block_cache.read_block(block_id)
+        #[cfg(feature = "block_cache")]
+        {
+            self.block_cache.read_block(block_id)
+        }
+        #[cfg(not(feature = "block_cache"))]
+        {
+            self.block_device.read_block(block_id)
+        }
     }
 
     /// Write a block to block device
     pub(super) fn write_block(&self, block: &Block) {
-        self.block_cache.write_block(block)
+        #[cfg(feature = "block_cache")]
+        {
+            self.block_cache.write_block(block)
+        }
+        #[cfg(not(feature = "block_cache"))]
+        {
+            self.block_device.write_block(block)
+        }
     }
 
     /// Read super block from block device

+ 32 - 2
src/ext4_defs/cache.rs

@@ -1,7 +1,10 @@
+#![cfg(feature = "block_cache")]
+
 use crate::constants::*;
 use crate::prelude::*;
 use crate::Block;
 use crate::BlockDevice;
+use axsync::Mutex;
 
 /// Write-back cache slot.
 #[derive(Debug, Clone, Copy, Default)]
@@ -41,13 +44,13 @@ impl CacheSet {
         set
     }
 
-    /// Link LRU list.
+    /// Link 2 LRU list nodes.
     fn link(&mut self, prev: u8, cur: u8) {
         self.slots[prev as usize].next = cur;
         self.slots[cur as usize].prev = prev;
     }
 
-    /// Access a block in the cache set
+    /// Access a block in the cache set.
     fn access(&mut self, block_id: PBlockId) -> usize {
         // Check if there is a slot allocated for the block
         let slot = self
@@ -143,4 +146,31 @@ impl BlockCache {
             slot.dirty = true;
         }
     }
+
+    /// Flush a block to disk.
+    #[allow(unused)]
+    pub fn flush(&self, block_id: PBlockId) {
+        let mut cache = self.cache.lock();
+        let set_id = block_id as usize % CACHE_SIZE;
+        let slot_id = cache[set_id].access(block_id) as usize;
+        let slot = &mut cache[set_id].slots[slot_id];
+        if slot.valid && slot.dirty {
+            self.block_dev.write_block(&slot.block);
+            slot.dirty = false;
+        }
+    }
+
+    /// Flush all blocks to disk.
+    pub fn flush_all(&self) {
+        let mut cache = self.cache.lock();
+        for set in cache.iter_mut() {
+            for slot in set.slots.iter_mut() {
+                if slot.valid && slot.dirty {
+                    info!("Flushing block {} to disk", slot.block.id);
+                    self.block_dev.write_block(&slot.block);
+                    slot.dirty = false;
+                }
+            }
+        }
+    }
 }

+ 6 - 2
src/ext4_defs/mod.rs

@@ -17,7 +17,6 @@
 mod bitmap;
 mod block;
 mod block_group;
-mod cache;
 mod crc;
 mod dir;
 mod extent;
@@ -27,10 +26,12 @@ mod mount_point;
 mod super_block;
 mod xattr;
 
+#[cfg(feature = "block_cache")]
+mod cache;
+
 pub use bitmap::*;
 pub use block::*;
 pub use block_group::*;
-pub use cache::*;
 pub use dir::*;
 pub use extent::*;
 pub use file::*;
@@ -38,6 +39,9 @@ pub use inode::*;
 pub use super_block::*;
 pub use xattr::*;
 
+#[cfg(feature = "block_cache")]
+pub use cache::*;
+
 /// All file types. Also matches the defination in directory entries.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[repr(u8)]

+ 0 - 1
src/prelude.rs

@@ -23,7 +23,6 @@ pub(crate) use core::ffi::CStr;
 pub(crate) use core::fmt::Debug;
 pub(crate) use core::mem::{self, size_of};
 pub(crate) use core::ptr;
-pub(crate) use axsync::Mutex;
 
 pub(crate) use log::{debug, info, trace, warn};