diff --git a/Cargo.lock b/Cargo.lock index b51c28bc..aae7d437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4784,7 +4784,7 @@ dependencies = [ [[package]] name = "rsext4" version = "0.1.0" -source = "git+https://github.com/Dirinkbottle/rsext4.git?branch=main#51110c1413aaa2ac183e2af80ce07cdee560545d" +source = "git+https://github.com/Dirinkbottle/rsext4.git?branch=main#0198aa5142eeceaeac7182792ccc75930d951516" dependencies = [ "bitflags 2.10.0", "lazy_static", diff --git a/modules/axfs/src/fs/ext4fs.rs b/modules/axfs/src/fs/ext4fs.rs index 010b4735..54eaafc0 100644 --- a/modules/axfs/src/fs/ext4fs.rs +++ b/modules/axfs/src/fs/ext4fs.rs @@ -144,6 +144,22 @@ impl FileWrapper { } } + /// Flush all dirty caches to disk (bitmap, inode table, data blocks, superblock, group descriptors). + /// Should be called after metadata-modifying operations (create, remove, rename) to ensure consistency. + fn sync_to_disk(&self) { + let mut fs = self.fs.lock(); + match &self.inner { + Ext4Inner::Disk(inner) => { + let mut inner = inner.lock(); + fs.sync_filesystem(&mut *inner).ok(); + } + Ext4Inner::Partition(inner) => { + let mut inner = inner.lock(); + fs.sync_filesystem(&mut *inner).ok(); + } + } + } + fn path_deal_with(&self, path: &str) -> String { if path.starts_with('/') { debug!("path_deal_with: {}", path); @@ -213,31 +229,34 @@ impl VfsNodeOps for FileWrapper { return Ok(()); } - let mut fs = self.fs.lock(); - match self.inner { - Ext4Inner::Disk(ref inner) => { - let mut inner = inner.lock(); - match ty { - VfsNodeType::Dir => { - mkdir(&mut *inner, &mut *fs, &fpath); - } - _ => { - mkfile(&mut *inner, &mut *fs, &fpath, None, None); + { + let mut fs = self.fs.lock(); + match self.inner { + Ext4Inner::Disk(ref inner) => { + let mut inner = inner.lock(); + match ty { + VfsNodeType::Dir => { + mkdir(&mut *inner, &mut *fs, &fpath); + } + _ => { + mkfile(&mut *inner, &mut *fs, &fpath, None, None); + } } } - } - Ext4Inner::Partition(ref inner) => { - let mut inner = inner.lock(); - match ty { - VfsNodeType::Dir => { - mkdir(&mut *inner, &mut *fs, &fpath); - } - _ => { - mkfile(&mut *inner, &mut *fs, &fpath, None, None); + Ext4Inner::Partition(ref inner) => { + let mut inner = inner.lock(); + match ty { + VfsNodeType::Dir => { + mkdir(&mut *inner, &mut *fs, &fpath); + } + _ => { + mkfile(&mut *inner, &mut *fs, &fpath, None, None); + } } } } } + self.sync_to_disk(); Ok(()) } @@ -246,40 +265,43 @@ impl VfsNodeOps for FileWrapper { let fpath = self.path_deal_with(path); assert!(!fpath.is_empty()); // already check at `root.rs` - let mut fs = self.fs.lock(); - let (_inode_num, inode) = match self.inner { - Ext4Inner::Disk(ref inner) => { - let mut inner = inner.lock(); - get_inode_with_num(&mut *fs, &mut *inner, &fpath) - .map_err(|_| VfsError::Io)? - .ok_or(VfsError::NotFound)? - } - Ext4Inner::Partition(ref inner) => { - let mut inner = inner.lock(); - get_inode_with_num(&mut *fs, &mut *inner, &fpath) - .map_err(|_| VfsError::Io)? - .ok_or(VfsError::NotFound)? - } - }; + { + let mut fs = self.fs.lock(); + let (_inode_num, inode) = match self.inner { + Ext4Inner::Disk(ref inner) => { + let mut inner = inner.lock(); + get_inode_with_num(&mut *fs, &mut *inner, &fpath) + .map_err(|_| VfsError::Io)? + .ok_or(VfsError::NotFound)? + } + Ext4Inner::Partition(ref inner) => { + let mut inner = inner.lock(); + get_inode_with_num(&mut *fs, &mut *inner, &fpath) + .map_err(|_| VfsError::Io)? + .ok_or(VfsError::NotFound)? + } + }; - match self.inner { - Ext4Inner::Disk(ref inner) => { - let mut inner = inner.lock(); - if inode.is_dir() { - delete_dir(&mut *fs, &mut *inner, &fpath); - } else { - unlink(&mut *fs, &mut *inner, &fpath); + match self.inner { + Ext4Inner::Disk(ref inner) => { + let mut inner = inner.lock(); + if inode.is_dir() { + delete_dir(&mut *fs, &mut *inner, &fpath); + } else { + unlink(&mut *fs, &mut *inner, &fpath); + } } - } - Ext4Inner::Partition(ref inner) => { - let mut inner = inner.lock(); - if inode.is_dir() { - delete_dir(&mut *fs, &mut *inner, &fpath); - } else { - unlink(&mut *fs, &mut *inner, &fpath); + Ext4Inner::Partition(ref inner) => { + let mut inner = inner.lock(); + if inode.is_dir() { + delete_dir(&mut *fs, &mut *inner, &fpath); + } else { + unlink(&mut *fs, &mut *inner, &fpath); + } } } } + self.sync_to_disk(); Ok(()) } @@ -465,6 +487,7 @@ impl VfsNodeOps for FileWrapper { .map_err(|_| VfsError::Io)?; } }; + self.sync_to_disk(); Ok(buf.len()) } @@ -480,6 +503,7 @@ impl VfsNodeOps for FileWrapper { let _ = truncate(&mut *inner, &mut *fs, &self.path, size); } } + self.sync_to_disk(); Ok(()) } @@ -500,6 +524,7 @@ impl VfsNodeOps for FileWrapper { let _ = mv(&mut *fs, &mut *inner, &src_fpath, &dst_fpath); } } + self.sync_to_disk(); Ok(()) } diff --git a/modules/axfs/src/root.rs b/modules/axfs/src/root.rs index 5fb1d971..6d9877bc 100644 --- a/modules/axfs/src/root.rs +++ b/modules/axfs/src/root.rs @@ -440,6 +440,7 @@ pub fn mount_virtual_fs(mut root_dir: RootDirectory) { panic!("Failed to mount virtual filesystems: {:?}", e); } + // Initialize global state let root_dir = Arc::new(root_dir); ROOT_DIR.init_once(root_dir.clone());