From bc07169798a13af77741fc42856e0270c7823320 Mon Sep 17 00:00:00 2001 From: longjin Date: Fri, 19 Dec 2025 11:38:44 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(ext4):=20=E4=BF=AE=E5=A4=8D=E6=AD=BB?= =?UTF-8?q?=E9=94=81=E9=97=AE=E9=A2=98=E5=B9=B6=E5=A2=9E=E5=BC=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=B3=BB=E7=BB=9F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复了ext4 inode读写操作中的自旋锁死锁问题 - 添加了父目录指针支持,实现parent()方法 - 改进了块设备寻址逻辑,统一使用512字节LBA - 增强了根文件系统探测机制,支持ext4和FAT自动识别 - 修复了ELF加载器中解释器路径查找问题 - 更新了another_ext4依赖版本 Signed-off-by: longjin --- kernel/Cargo.lock | 2 +- kernel/crates/kdepends/Cargo.toml | 2 +- kernel/src/filesystem/ext4/filesystem.rs | 20 ++- kernel/src/filesystem/ext4/gendisk.rs | 21 ++- kernel/src/filesystem/ext4/inode.rs | 184 ++++++++++++++++------- kernel/src/filesystem/vfs/vcore.rs | 90 +++++++++-- kernel/src/libs/elf.rs | 16 +- kernel/src/process/exec.rs | 4 +- tools/run-qemu.sh | 2 +- 9 files changed, 248 insertions(+), 93 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index beef5d893..914ec7d08 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -57,7 +57,7 @@ dependencies = [ [[package]] name = "another_ext4" version = "0.1.0" -source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/another_ext4.git?rev=bf782ff294#bf782ff2947b57ba89503824eada5eb3c20a2e2a" +source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/another_ext4.git?rev=8bc384254c#8bc384254c7b7464afcdc312fb0c0aa622e2467e" dependencies = [ "bitflags 2.9.1", "log", diff --git a/kernel/crates/kdepends/Cargo.toml b/kernel/crates/kdepends/Cargo.toml index b35146c77..3e7237f88 100644 --- a/kernel/crates/kdepends/Cargo.toml +++ b/kernel/crates/kdepends/Cargo.toml @@ -11,7 +11,7 @@ crc = { path = "../crc" } memoffset = "0.9.0" ringbuffer = "0.15.0" xarray = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/xarray", rev = "de93b57c34", features = ["slab-friendly"] } -another_ext4 = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/another_ext4.git", rev = "bf782ff294", default-features = false } +another_ext4 = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/another_ext4.git", rev = "8bc384254c", default-features = false } # 一个无锁MPSC队列 [dependencies.thingbuf] diff --git a/kernel/src/filesystem/ext4/filesystem.rs b/kernel/src/filesystem/ext4/filesystem.rs index ffbbb604d..4d9fc8dc5 100644 --- a/kernel/src/filesystem/ext4/filesystem.rs +++ b/kernel/src/filesystem/ext4/filesystem.rs @@ -73,14 +73,18 @@ impl Ext4FileSystem { let raw_dev = mount_data.device_num(); let fs = another_ext4::Ext4::load(mount_data)?; let root_inode: Arc = - Arc::new(LockedExt4Inode(SpinLock::new(Ext4Inode { - inner_inode_num: another_ext4::EXT4_ROOT_INO, - fs_ptr: Weak::default(), - page_cache: None, - children: BTreeMap::new(), - dname: DName::from("/"), - vfs_inode_id: generate_inode_id(), - }))); + Arc::new_cyclic(|self_ref: &Weak| { + LockedExt4Inode(SpinLock::new(Ext4Inode { + inner_inode_num: another_ext4::EXT4_ROOT_INO, + fs_ptr: Weak::default(), + page_cache: None, + children: BTreeMap::new(), + dname: DName::from("/"), + vfs_inode_id: generate_inode_id(), + parent: self_ref.clone(), + self_ref: self_ref.clone(), + })) + }); let fs = Arc::new(Ext4FileSystem { fs, diff --git a/kernel/src/filesystem/ext4/gendisk.rs b/kernel/src/filesystem/ext4/gendisk.rs index 12fb83a61..f00c450b7 100644 --- a/kernel/src/filesystem/ext4/gendisk.rs +++ b/kernel/src/filesystem/ext4/gendisk.rs @@ -3,15 +3,24 @@ use kdepends::another_ext4; use system_error::SystemError; use crate::driver::base::block::gendisk::GenDisk; +use crate::driver::base::block::block_device::LBA_SIZE; impl GenDisk { fn convert_from_ext4_blkid(&self, ext4_blkid: u64) -> (usize, usize, usize) { - let size = self.block_size_log2(); - let start_block_offset = - ext4_blkid as usize * (another_ext4::BLOCK_SIZE / (1 << size as usize)); - let lba_id_start = self.block_offset_2_disk_blkid(start_block_offset); - let block_count = another_ext4::BLOCK_SIZE / (1 << size as usize); - (start_block_offset, lba_id_start, block_count) + // another_ext4 的逻辑块固定为 4096 字节(another_ext4::BLOCK_SIZE)。 + // + // DragonOS 块设备的“LBA”语义固定为 512 字节(LBA_SIZE)。 + // GenDisk::block_offset_2_disk_blkid() 与 BlockDevice::read_at()/write_at() + // 都是以 512B LBA 为单位进行寻址的。 + // + // 因此这里必须把 ext4 的 4K block id 转成“512B LBA 偏移”, + // 不能使用底层设备的 blk_size_log2(否则当设备上报 4K 物理块时会导致寻址单位混乱, + // 进而读到错误数据,表现为 extent tree 解析失败/随机 ENOENT)。 + let blocks_per_ext4_block = another_ext4::BLOCK_SIZE / LBA_SIZE; + let start_lba_offset = ext4_blkid as usize * blocks_per_ext4_block; + let lba_id_start = self.block_offset_2_disk_blkid(start_lba_offset); + let block_count = blocks_per_ext4_block; + (start_lba_offset, lba_id_start, block_count) } } diff --git a/kernel/src/filesystem/ext4/inode.rs b/kernel/src/filesystem/ext4/inode.rs index d4facf8eb..83a5809f1 100644 --- a/kernel/src/filesystem/ext4/inode.rs +++ b/kernel/src/filesystem/ext4/inode.rs @@ -37,6 +37,12 @@ pub struct Ext4Inode { // 对应vfs的inode id,用于标识系统中唯一的inode pub(super) vfs_inode_id: InodeId, + + // 指向父级IndexNode的Weak指针 + pub(super) parent: Weak, + + // 指向自身的Weak指针,用于获取Arc + pub(super) self_ref: Weak, } #[derive(Debug)] @@ -71,7 +77,14 @@ impl IndexNode for LockedExt4Inode { another_ext4::InodeMode::from_bits_truncate(file_mode.bits() as u16), )?; let dname = DName::from(name); - let inode = LockedExt4Inode::new(id, guard.fs_ptr.clone(), dname.clone()); + // 通过self_ref获取Arc,然后转换为Arc + let self_arc = guard.self_ref.upgrade().ok_or(SystemError::ENOENT)?; + let inode = LockedExt4Inode::new( + id, + guard.fs_ptr.clone(), + dname.clone(), + Some(Arc::downgrade(&self_arc)), + ); // 更新 children 缓存 guard.children.insert(dname, inode.clone()); drop(guard); @@ -99,28 +112,40 @@ impl IndexNode for LockedExt4Inode { buf: &mut [u8], data: PrivateData, ) -> Result { - let guard = self.0.lock(); - let len = core::cmp::min(len, buf.len()); let buf = &mut buf[0..len]; - let ext4 = &guard.concret_fs().fs; - if let Some(page_cache) = &guard.page_cache { + + // 关键修复:不要在持有 Ext4 inode 自旋锁期间调用 PageCache::{read,write}。 + // PageCache 读写路径内部会调用 inode.metadata() 获取文件大小: + // - prepare_read(): inode.metadata() + // 若此处持有 inode 锁,则会在 metadata() 再次尝试获取同一把锁而自旋死锁。 + let (fs, inode_num, page_cache) = { + let guard = self.0.lock(); + ( + guard.concret_fs(), + guard.inner_inode_num, + guard.page_cache.clone(), + ) + }; + + if let Some(page_cache) = page_cache { let time = PosixTimeSpec::now().tv_sec.to_u32().unwrap_or_else(|| { log::warn!("Failed to get current time, using 0"); 0 }); - ext4.setattr( - guard.inner_inode_num, - None, - None, - None, - None, - Some(time), - None, - None, - None, - ) - .map_err(SystemError::from)?; + fs.fs + .setattr( + inode_num, + None, + None, + None, + None, + Some(time), + None, + None, + None, + ) + .map_err(SystemError::from)?; page_cache.read(offset, buf) } else { self.read_direct(offset, len, buf, data) @@ -128,13 +153,15 @@ impl IndexNode for LockedExt4Inode { } fn read_sync(&self, offset: usize, buf: &mut [u8]) -> Result { - let guard = self.0.lock(); - let ext4 = &guard.concret_fs().fs; - let inode_num = guard.inner_inode_num; - match ext4.getattr(inode_num)?.ftype { + let (fs, inode_num) = { + let guard = self.0.lock(); + (guard.concret_fs(), guard.inner_inode_num) + }; + match fs.fs.getattr(inode_num)?.ftype { FileType::Directory => Err(SystemError::EISDIR), FileType::Unknown => Err(SystemError::EROFS), - FileType::RegularFile => ext4.read(inode_num, offset, buf).map_err(From::from), + FileType::RegularFile => fs.fs.read(inode_num, offset, buf).map_err(From::from), + FileType::SymLink => fs.fs.readlink(inode_num, offset, buf).map_err(From::from), _ => Err(SystemError::EINVAL), } } @@ -157,30 +184,39 @@ impl IndexNode for LockedExt4Inode { buf: &[u8], data: PrivateData, ) -> Result { - let guard = self.0.lock(); - let ext4 = &guard.concret_fs().fs; let len = core::cmp::min(len, buf.len()); let buf = &buf[0..len]; - if let Some(page_cache) = &guard.page_cache { - let write_len = PageCache::write(page_cache, offset, buf)?; - let old_file_size = ext4.getattr(guard.inner_inode_num)?.size; + + let (fs, inode_num, page_cache) = { + let guard = self.0.lock(); + ( + guard.concret_fs(), + guard.inner_inode_num, + guard.page_cache.clone(), + ) + }; + + if let Some(page_cache) = page_cache { + let write_len = PageCache::write(&page_cache, offset, buf)?; + let old_file_size = fs.fs.getattr(inode_num)?.size; let current_file_size = core::cmp::max(old_file_size, (offset + write_len) as u64); let time = PosixTimeSpec::now().tv_sec.to_u32().unwrap_or_else(|| { log::warn!("Failed to get current time, using 0"); 0 }); - ext4.setattr( - guard.inner_inode_num, - None, - None, - None, - Some(current_file_size), - None, - Some(time), - None, - None, - ) - .map_err(SystemError::from)?; + fs.fs + .setattr( + inode_num, + None, + None, + None, + Some(current_file_size), + None, + Some(time), + None, + None, + ) + .map_err(SystemError::from)?; Ok(write_len) } else { self.write_direct(offset, len, buf, data) @@ -188,13 +224,14 @@ impl IndexNode for LockedExt4Inode { } fn write_sync(&self, offset: usize, buf: &[u8]) -> Result { - let guard = self.0.lock(); - let ext4 = &guard.concret_fs().fs; - let inode_num = guard.inner_inode_num; - match ext4.getattr(inode_num)?.ftype { + let (fs, inode_num) = { + let guard = self.0.lock(); + (guard.concret_fs(), guard.inner_inode_num) + }; + match fs.fs.getattr(inode_num)?.ftype { FileType::Directory => Err(SystemError::EISDIR), FileType::Unknown => Err(SystemError::EROFS), - FileType::RegularFile => ext4.write(inode_num, offset, buf).map_err(From::from), + FileType::RegularFile => fs.fs.write(inode_num, offset, buf).map_err(From::from), _ => Err(SystemError::EINVAL), } } @@ -225,11 +262,31 @@ impl IndexNode for LockedExt4Inode { return Ok(child.clone() as Arc); } let next_inode = guard.concret_fs().fs.lookup(guard.inner_inode_num, name)?; - let inode = LockedExt4Inode::new(next_inode, guard.fs_ptr.clone(), dname.clone()); + // 通过self_ref获取Arc,然后转换为Arc + let self_arc = guard.self_ref.upgrade().ok_or(SystemError::ENOENT)?; + let inode = LockedExt4Inode::new( + next_inode, + guard.fs_ptr.clone(), + dname.clone(), + Some(Arc::downgrade(&self_arc)), + ); guard.children.insert(dname, inode.clone()); Ok(inode) } + fn parent(&self) -> Result, SystemError> { + // 只有目录才有父目录的概念 + // 先检查当前inode是否为目录 + let guard = self.0.lock(); + + // 如果存储了父级指针,直接返回 + if let Some(parent) = guard.parent.upgrade() { + return Ok(parent); + } + + Err(SystemError::ENOENT) + } + fn list(&self) -> Result, SystemError> { let guard = self.0.lock(); let dentry = guard.concret_fs().fs.listdir(guard.inner_inode_num)?; @@ -292,12 +349,18 @@ impl IndexNode for LockedExt4Inode { } fn metadata(&self) -> Result { - let guard = self.0.lock(); - let ext4 = &guard.concret_fs().fs; - let attr = ext4.getattr(guard.inner_inode_num)?; - let raw_dev = guard.fs_ptr.upgrade().unwrap().raw_dev; + let (fs, inode_num, vfs_inode_id) = { + let guard = self.0.lock(); + ( + guard.concret_fs(), + guard.inner_inode_num, + guard.vfs_inode_id, + ) + }; + let attr = fs.fs.getattr(inode_num)?; + let raw_dev = fs.raw_dev; Ok(vfs::Metadata { - inode_id: guard.vfs_inode_id, + inode_id: vfs_inode_id, size: attr.size as i64, blk_size: another_ext4::BLOCK_SIZE, blocks: attr.blocks as usize, @@ -445,12 +508,18 @@ impl LockedExt4Inode { inode_num: u32, fs_ptr: Weak, dname: DName, + parent: Option>, ) -> Arc { - let inode = Arc::new(LockedExt4Inode(SpinLock::new(Ext4Inode::new( - inode_num, fs_ptr, dname, - )))); + let inode = Arc::new({ + LockedExt4Inode(SpinLock::new(Ext4Inode::new( + inode_num, fs_ptr, dname, parent, + ))) + }); let mut guard = inode.0.lock(); + // 设置self_ref + guard.self_ref = Arc::downgrade(&inode); + let page_cache = PageCache::new(Some(Arc::downgrade(&inode) as Weak)); guard.page_cache = Some(page_cache); @@ -482,7 +551,12 @@ impl Ext4Inode { .expect("Ext4FileSystem should be alive") } - pub fn new(inode_num: u32, fs_ptr: Weak, dname: DName) -> Self { + pub fn new( + inode_num: u32, + fs_ptr: Weak, + dname: DName, + parent: Option>, + ) -> Self { Self { inner_inode_num: inode_num, fs_ptr, @@ -490,6 +564,8 @@ impl Ext4Inode { children: BTreeMap::new(), dname, vfs_inode_id: generate_inode_id(), + parent: parent.unwrap_or_else(|| Weak::new()), + self_ref: Weak::new(), // 将在LockedExt4Inode::new()中设置 } } } diff --git a/kernel/src/filesystem/vfs/vcore.rs b/kernel/src/filesystem/vfs/vcore.rs index e8bfe626f..ceb3d8f72 100644 --- a/kernel/src/filesystem/vfs/vcore.rs +++ b/kernel/src/filesystem/vfs/vcore.rs @@ -1,7 +1,7 @@ use core::{hint::spin_loop, sync::atomic::Ordering}; -use alloc::sync::Arc; -use log::{error, info}; +use alloc::{string::ToString, sync::Arc}; +use log::{error, info, warn}; use system_error::SystemError; use crate::libs::casting::DowncastArc; @@ -11,6 +11,8 @@ use crate::{ filesystem::{ devfs::devfs_init, devpts::devpts_init, + ext4::filesystem::Ext4FileSystem, + fat::bpb::BiosParameterBlock, fat::fs::FATFileSystem, procfs::procfs_init, sysfs::sysfs_init, @@ -139,6 +141,51 @@ pub(crate) fn try_find_gendisk(path: &str) -> Option> { return None; } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum RootFsKind { + Ext4, + Fat, +} + +/// 探测 ext2/3/4:检查 superblock magic(0xEF53)。 +/// +/// Linux/ext 家族的 superblock 位于分区内偏移 1024 字节处, +/// s_magic 位于 superblock 内偏移 0x38(56)处。 +fn probe_ext_fs(gendisk: &Arc) -> Result { + const EXT_SUPERBLOCK_OFFSET: usize = 1024; + const EXT_MAGIC_OFFSET_IN_SB: usize = 0x38; + const EXT_MAGIC: u16 = 0xEF53; + + let mut magic = [0u8; 2]; + gendisk.read_at_bytes( + &mut magic, + EXT_SUPERBLOCK_OFFSET + EXT_MAGIC_OFFSET_IN_SB, + )?; + Ok(u16::from_le_bytes(magic) == EXT_MAGIC) +} + +/// 探测 FAT:复用 FAT BPB 解析/校验逻辑,避免误判。 +fn probe_fat_fs(gendisk: &Arc) -> bool { + BiosParameterBlock::new(gendisk).is_ok() +} + +fn probe_rootfs_kind(gendisk: &Arc) -> Option { + match probe_ext_fs(gendisk) { + Ok(true) => return Some(RootFsKind::Ext4), + Ok(false) => {} + Err(e) => { + // 探测阶段不应阻塞启动;继续尝试其他 FS 探测/初始化。 + warn!("Rootfs probe: read ext superblock failed: {:?}", e); + } + } + + if probe_fat_fs(gendisk) { + return Some(RootFsKind::Fat); + } + + None +} + pub fn mount_root_fs() -> Result<(), SystemError> { info!("Try to mount root fs..."); block_dev_manager().print_gendisks(); @@ -152,26 +199,39 @@ pub fn mount_root_fs() -> Result<(), SystemError> { .ok_or(SystemError::ENODEV)? }; - let fatfs: Result, SystemError> = FATFileSystem::new(gendisk); - if fatfs.is_err() { - error!( - "Failed to initialize fatfs, code={:?}", - fatfs.as_ref().err() - ); - loop { - spin_loop(); + let kind = probe_rootfs_kind(&gendisk); + + let rootfs: Result, SystemError> = match kind { + Some(RootFsKind::Ext4) => Ext4FileSystem::from_gendisk(gendisk.clone()), + Some(RootFsKind::Fat) => Ok(FATFileSystem::new(gendisk.clone())?), + None => { + // 兜底:按常见顺序尝试初始化(ext4 -> fat),便于未来扩展 probe 或处理特殊镜像。 + Ext4FileSystem::from_gendisk(gendisk.clone()).or_else(|_| { + let fat: Arc = FATFileSystem::new(gendisk.clone())?; + Ok(fat) + }) } - } - let fatfs: Arc = fatfs.unwrap(); - let r = migrate_virtual_filesystem(fatfs); + }; + + let rootfs = match rootfs { + Ok(fs) => fs, + Err(e) => { + error!("Failed to initialize rootfs filesystem: {:?}", e); + loop { + spin_loop(); + } + } + }; + let fs_name = rootfs.name().to_string(); + let r = migrate_virtual_filesystem(rootfs.clone()); if r.is_err() { - error!("Failed to migrate virtual filesyst em to FAT32!"); + error!("Failed to migrate virtual filesystem to rootfs ({}).", fs_name); loop { spin_loop(); } } - info!("Successfully migrate rootfs to FAT32!"); + info!("Successfully migrate rootfs to {}!", fs_name); return Ok(()); } diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index 4cb65754c..7b31af27e 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -18,6 +18,7 @@ use system_error::SystemError; use crate::{ arch::{CurrentElfArch, MMArch}, driver::base::block::SeekFrom, + filesystem::vfs::VFS_MAX_FOLLOW_SYMLINK_TIMES, libs::align::page_align_up, mm::{ allocator::page_frame::{PageFrameCount, VirtPageFrame}, @@ -788,10 +789,17 @@ impl BinaryLoader for ElfLoader { )) })?; let pwd = ProcessManager::current_pcb().pwd_inode(); - let inode = pwd.lookup(interpreter_path).map_err(|_| { - log::error!("Failed to find interpreter path: {}", interpreter_path); - return ExecError::InvalidParemeter; - })?; + let inode = pwd + .lookup_follow_symlink(interpreter_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) + .map_err(|e| { + // Linux 语义:动态链接器(解释器)路径不存在时,execve 需返回 ENOENT。 + log::error!( + "Failed to find interpreter path: {} (err={:?})", + interpreter_path, + e + ); + ExecError::SystemError(SystemError::ENOENT) + })?; // log::debug!("opening interpreter at :{}", interpreter_path); interpreter = Some( ExecParam::new(inode, param.vm().clone(), ExecParamFlags::EXEC).map_err(|e| { diff --git a/kernel/src/process/exec.rs b/kernel/src/process/exec.rs index 6d606902f..7a1f88533 100644 --- a/kernel/src/process/exec.rs +++ b/kernel/src/process/exec.rs @@ -231,9 +231,7 @@ pub fn load_binary_file(param: &mut ExecParam) -> Result Date: Fri, 19 Dec 2025 20:49:59 +0800 Subject: [PATCH 2/3] 1 --- kernel/Cargo.lock | 10 +++++++++- kernel/src/filesystem/ext4/gendisk.rs | 2 +- kernel/src/filesystem/vfs/vcore.rs | 10 +++++----- tools/run-qemu.sh | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 914ec7d08..ab5491ed5 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -54,6 +54,14 @@ dependencies = [ "libc", ] +[[package]] +name = "another_ext4" +version = "0.1.0" +dependencies = [ + "bitflags 2.9.1", + "log", +] + [[package]] name = "another_ext4" version = "0.1.0" @@ -763,7 +771,7 @@ version = "0.1.0" name = "kdepends" version = "0.1.0" dependencies = [ - "another_ext4", + "another_ext4 0.1.0 (git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/another_ext4.git?rev=8bc384254c)", "crc", "memoffset", "ringbuffer", diff --git a/kernel/src/filesystem/ext4/gendisk.rs b/kernel/src/filesystem/ext4/gendisk.rs index f00c450b7..56f5acb3d 100644 --- a/kernel/src/filesystem/ext4/gendisk.rs +++ b/kernel/src/filesystem/ext4/gendisk.rs @@ -2,8 +2,8 @@ use alloc::boxed::Box; use kdepends::another_ext4; use system_error::SystemError; -use crate::driver::base::block::gendisk::GenDisk; use crate::driver::base::block::block_device::LBA_SIZE; +use crate::driver::base::block::gendisk::GenDisk; impl GenDisk { fn convert_from_ext4_blkid(&self, ext4_blkid: u64) -> (usize, usize, usize) { diff --git a/kernel/src/filesystem/vfs/vcore.rs b/kernel/src/filesystem/vfs/vcore.rs index ceb3d8f72..c76b5e6cf 100644 --- a/kernel/src/filesystem/vfs/vcore.rs +++ b/kernel/src/filesystem/vfs/vcore.rs @@ -157,10 +157,7 @@ fn probe_ext_fs(gendisk: &Arc) -> Result { const EXT_MAGIC: u16 = 0xEF53; let mut magic = [0u8; 2]; - gendisk.read_at_bytes( - &mut magic, - EXT_SUPERBLOCK_OFFSET + EXT_MAGIC_OFFSET_IN_SB, - )?; + gendisk.read_at_bytes(&mut magic, EXT_SUPERBLOCK_OFFSET + EXT_MAGIC_OFFSET_IN_SB)?; Ok(u16::from_le_bytes(magic) == EXT_MAGIC) } @@ -226,7 +223,10 @@ pub fn mount_root_fs() -> Result<(), SystemError> { let fs_name = rootfs.name().to_string(); let r = migrate_virtual_filesystem(rootfs.clone()); if r.is_err() { - error!("Failed to migrate virtual filesystem to rootfs ({}).", fs_name); + error!( + "Failed to migrate virtual filesystem to rootfs ({}).", + fs_name + ); loop { spin_loop(); } diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index efcbb4faf..cd12a8f93 100755 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -252,7 +252,7 @@ if [ ${QEMU_NOGRAPHIC} == true ]; then QEMU_DEVICES+=" -device virtio-serial-device -device virtconsole,chardev=mux " fi - KERNEL_CMDLINE=" root=/dev/vda console=/dev/hvc0 ${KERNEL_CMDLINE}" + KERNEL_CMDLINE=" console=/dev/hvc0 ${KERNEL_CMDLINE}" QEMU_MONITOR="" QEMU_ARGUMENT+=" --nographic " From a45dbd930711d2c82d761c4ff18b65588617ab43 Mon Sep 17 00:00:00 2001 From: longjin Date: Fri, 19 Dec 2025 21:51:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat(filesystem):=20=E4=B8=BAext4=E5=92=8Cf?= =?UTF-8?q?at=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=8E=A2=E6=B5=8B=E6=96=B9=E6=B3=95=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Ext4FileSystem和FATFileSystem中新增probe方法,用于探测gendisk是否包含对应文 件系统 - 重构vcore.rs中的文件系统探测逻辑,使用新的probe方法替代原有的独立探测函数 - 优化Ext4Inode构造函数中parent字段的默认值设置,使用unwrap_or_default替代unwrap _or_else - 在rcS启动脚本中添加PATH环境变量设置 Signed-off-by: longjin --- kernel/src/filesystem/ext4/filesystem.rs | 7 +++++++ kernel/src/filesystem/ext4/inode.rs | 2 +- kernel/src/filesystem/fat/fs.rs | 5 +++++ kernel/src/filesystem/vfs/vcore.rs | 24 ++---------------------- user/sysconfig/etc/init.d/rcS | 3 +++ 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/kernel/src/filesystem/ext4/filesystem.rs b/kernel/src/filesystem/ext4/filesystem.rs index 4d9fc8dc5..a41ebf3e3 100644 --- a/kernel/src/filesystem/ext4/filesystem.rs +++ b/kernel/src/filesystem/ext4/filesystem.rs @@ -69,6 +69,13 @@ impl FileSystem for Ext4FileSystem { } impl Ext4FileSystem { + /// 探测 gendisk 是否包含 ext4 文件系统 + pub fn probe(gendisk: &Arc) -> Result { + Ok(another_ext4::Ext4::load(gendisk.clone()) + .map(|_| true) + .unwrap_or(false)) + } + pub fn from_gendisk(mount_data: Arc) -> Result, SystemError> { let raw_dev = mount_data.device_num(); let fs = another_ext4::Ext4::load(mount_data)?; diff --git a/kernel/src/filesystem/ext4/inode.rs b/kernel/src/filesystem/ext4/inode.rs index 83a5809f1..5ac63b067 100644 --- a/kernel/src/filesystem/ext4/inode.rs +++ b/kernel/src/filesystem/ext4/inode.rs @@ -564,7 +564,7 @@ impl Ext4Inode { children: BTreeMap::new(), dname, vfs_inode_id: generate_inode_id(), - parent: parent.unwrap_or_else(|| Weak::new()), + parent: parent.unwrap_or_default(), self_ref: Weak::new(), // 将在LockedExt4Inode::new()中设置 } } diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 9e3b8e5c6..fea097441 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -461,6 +461,11 @@ impl FileSystem for FATFileSystem { } impl FATFileSystem { + /// 探测 gendisk 是否包含 FAT 文件系统 + pub fn probe(gendisk: &Arc) -> bool { + BiosParameterBlock::new(gendisk).is_ok() + } + /// FAT12允许的最大簇号 pub const FAT12_MAX_CLUSTER: u32 = 0xFF5; /// FAT16允许的最大簇号 diff --git a/kernel/src/filesystem/vfs/vcore.rs b/kernel/src/filesystem/vfs/vcore.rs index c76b5e6cf..28e0f3207 100644 --- a/kernel/src/filesystem/vfs/vcore.rs +++ b/kernel/src/filesystem/vfs/vcore.rs @@ -12,7 +12,6 @@ use crate::{ devfs::devfs_init, devpts::devpts_init, ext4::filesystem::Ext4FileSystem, - fat::bpb::BiosParameterBlock, fat::fs::FATFileSystem, procfs::procfs_init, sysfs::sysfs_init, @@ -147,27 +146,8 @@ enum RootFsKind { Fat, } -/// 探测 ext2/3/4:检查 superblock magic(0xEF53)。 -/// -/// Linux/ext 家族的 superblock 位于分区内偏移 1024 字节处, -/// s_magic 位于 superblock 内偏移 0x38(56)处。 -fn probe_ext_fs(gendisk: &Arc) -> Result { - const EXT_SUPERBLOCK_OFFSET: usize = 1024; - const EXT_MAGIC_OFFSET_IN_SB: usize = 0x38; - const EXT_MAGIC: u16 = 0xEF53; - - let mut magic = [0u8; 2]; - gendisk.read_at_bytes(&mut magic, EXT_SUPERBLOCK_OFFSET + EXT_MAGIC_OFFSET_IN_SB)?; - Ok(u16::from_le_bytes(magic) == EXT_MAGIC) -} - -/// 探测 FAT:复用 FAT BPB 解析/校验逻辑,避免误判。 -fn probe_fat_fs(gendisk: &Arc) -> bool { - BiosParameterBlock::new(gendisk).is_ok() -} - fn probe_rootfs_kind(gendisk: &Arc) -> Option { - match probe_ext_fs(gendisk) { + match Ext4FileSystem::probe(gendisk) { Ok(true) => return Some(RootFsKind::Ext4), Ok(false) => {} Err(e) => { @@ -176,7 +156,7 @@ fn probe_rootfs_kind(gendisk: &Arc) -> Option { } } - if probe_fat_fs(gendisk) { + if FATFileSystem::probe(gendisk) { return Some(RootFsKind::Fat); } diff --git a/user/sysconfig/etc/init.d/rcS b/user/sysconfig/etc/init.d/rcS index 688e9d312..4c4a7c2bd 100755 --- a/user/sysconfig/etc/init.d/rcS +++ b/user/sysconfig/etc/init.d/rcS @@ -1,4 +1,7 @@ #!/bin/sh + +export PATH=/bin:/usr/bin:/usr/local/bin + echo "[rcS] Running system init script..." /bin/about.elf