From df4331d7e677cfa0a92a8b574ae0e6519d91662a Mon Sep 17 00:00:00 2001 From: Dirinkbottle <2909128143@qq.com> Date: Wed, 11 Feb 2026 16:42:57 +0800 Subject: [PATCH 1/4] fix(axfs): update rsext4 to fix journal playback data inconsistency The previous rsext4 version (dev-251222) had a bug where mount() reads superblock and group descriptors before journal_replay(), but never reloads them after replay. This causes in-memory metadata to be stale, leading to incorrect block allocation and data corruption (TEE htree authenc_decrypt_final error 0xFFFF3071) after system restart. Updated rsext4 to main branch which includes the fix. --- modules/axfs/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/axfs/Cargo.toml b/modules/axfs/Cargo.toml index f9bfd195..0a444b02 100644 --- a/modules/axfs/Cargo.toml +++ b/modules/axfs/Cargo.toml @@ -19,7 +19,7 @@ cap_access = "0.1" lazyinit = "0.2" spin = "0.9" log = "0.4" -rsext4 = {git = "https://github.com/Dirinkbottle/rsext4.git", tag = "dev-251222"} +rsext4 = {git = "https://github.com/Dirinkbottle/rsext4.git", branch = "main"} [dependencies.fatfs] default-features = false From d748e1a5cec065b34abff1a96b62b9700ba6bdc9 Mon Sep 17 00:00:00 2001 From: Dirinkbottle <2909128143@qq.com> Date: Wed, 11 Feb 2026 17:21:41 +0800 Subject: [PATCH 2/4] fix(axfs): update rsext4 to fix journal playback data inconsistency --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index fabdd385..b51c28bc 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?tag=dev-251222#376e253cc6b8767bc14ca5054fbc1ae49f7a8c8d" +source = "git+https://github.com/Dirinkbottle/rsext4.git?branch=main#51110c1413aaa2ac183e2af80ce07cdee560545d" dependencies = [ "bitflags 2.10.0", "lazy_static", From dd0a137b2d2fc96368f604ce5b61abd54c96f9dd Mon Sep 17 00:00:00 2001 From: Dirinkbottle <2909128143@qq.com> Date: Fri, 13 Feb 2026 13:07:33 +0800 Subject: [PATCH 3/4] fix(axfs):Fixed an issue that caused bitmap inconsistencies when restarting a guest machine using the rsext4 filesystem. Problem: After a client machine performs a file write operation and restarts, a "block is free" error occurs. Analysis: 1. rsext4 is designed with multi-level caching to improve runtime speed. However, currently, Axvisor does not perform any data synchronization during rsext4 integration. This means that if the machine modifies a file and shuts down immediately, the cache remains in memory, inevitably leading to hard drive failure. Solution: In the ext4fs access layer of rsext4, call `sync_to_disk` for all write operations to ensure timely synchronization, even if it results in some performance loss. --- Cargo.lock | 2 +- modules/axfs/src/fs/ext4fs.rs | 121 ++++++++++++++++++++-------------- modules/axfs/src/root.rs | 1 + 3 files changed, 75 insertions(+), 49 deletions(-) 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()); From 6f6d6224168928caa75e147e6e5240ab63574602 Mon Sep 17 00:00:00 2001 From: dirinkbottle <122192254+Dirinkbottle@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:47:45 +0800 Subject: [PATCH 4/4] fix:resovle cargo.lock flict --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f3687f5b..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#0198aa5142eeceaeac7182792ccc75930d951516 +source = "git+https://github.com/Dirinkbottle/rsext4.git?branch=main#0198aa5142eeceaeac7182792ccc75930d951516" dependencies = [ "bitflags 2.10.0", "lazy_static",