From 83c158e3b58138713e244ec8306d7fd3b8aa51e2 Mon Sep 17 00:00:00 2001 From: jiangjianfeng Date: Thu, 4 Dec 2025 08:17:27 +0000 Subject: [PATCH] Make device Inode behave like pointer --- kernel/src/device/registry/block.rs | 3 +- kernel/src/device/registry/char.rs | 5 +- kernel/src/fs/device.rs | 15 ++++- kernel/src/fs/ext2/impl_for_vfs/inode.rs | 16 +++-- kernel/src/fs/ramfs/fs.rs | 84 +++++++++++++++++------- kernel/src/fs/utils/inode.rs | 25 ++----- kernel/src/syscall/mknod.rs | 13 ++-- 7 files changed, 101 insertions(+), 60 deletions(-) diff --git a/kernel/src/device/registry/block.rs b/kernel/src/device/registry/block.rs index 6c61cfa3f..ac8b53cea 100644 --- a/kernel/src/device/registry/block.rs +++ b/kernel/src/device/registry/block.rs @@ -39,7 +39,8 @@ pub(super) fn init_in_first_process(fs_resolver: &FsResolver) -> Result<()> { for device in aster_block::collect_all() { let device = Arc::new(BlockFile::new(device)); if let Some(devtmpfs_path) = device.devtmpfs_path() { - add_node(device, &devtmpfs_path, fs_resolver)?; + let dev_id = device.id().as_encoded_u64(); + add_node(DeviceType::Block, dev_id, &devtmpfs_path, fs_resolver)?; } } diff --git a/kernel/src/device/registry/char.rs b/kernel/src/device/registry/char.rs index 88e2d8f79..0ed1e5985 100644 --- a/kernel/src/device/registry/char.rs +++ b/kernel/src/device/registry/char.rs @@ -8,7 +8,7 @@ use device_id::{DeviceId, MajorId}; use crate::{ fs::{ - device::{add_node, Device}, + device::{add_node, Device, DeviceType}, fs_resolver::FsResolver, }, prelude::*, @@ -115,7 +115,8 @@ impl Drop for MajorIdOwner { pub(super) fn init_in_first_process(fs_resolver: &FsResolver) -> Result<()> { for device in collect_all() { if let Some(devtmpfs_path) = device.devtmpfs_path() { - add_node(device, &devtmpfs_path, fs_resolver)?; + let dev_id = device.id().as_encoded_u64(); + add_node(DeviceType::Char, dev_id, &devtmpfs_path, fs_resolver)?; } } diff --git a/kernel/src/fs/device.rs b/kernel/src/fs/device.rs index dee58eb50..9882013cf 100644 --- a/kernel/src/fs/device.rs +++ b/kernel/src/fs/device.rs @@ -7,7 +7,7 @@ use crate::{ fs::{ fs_resolver::{FsPath, FsResolver}, path::Path, - utils::{mkmod, InodeType}, + utils::{mkmod, InodeType, MknodType}, }, prelude::*, }; @@ -51,7 +51,12 @@ pub enum DeviceType { /// This function should be called when registering a device. // // TODO: Figure out what should happen when unregistering the device. -pub fn add_node(device: Arc, path: &str, fs_resolver: &FsResolver) -> Result { +pub fn add_node( + dev_type: DeviceType, + dev_id: u64, + path: &str, + fs_resolver: &FsResolver, +) -> Result { let mut dev_path = fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?; let mut relative_path = { let relative_path = path.trim_start_matches('/'); @@ -79,7 +84,11 @@ pub fn add_node(device: Arc, path: &str, fs_resolver: &FsResolver) - Err(_) => { if path_remain.is_empty() { // Create the device node - dev_path = dev_path.mknod(next_name, mkmod!(a+rw), device.clone().into())?; + let mknod_type = match dev_type { + DeviceType::Block => MknodType::BlockDevice(dev_id), + DeviceType::Char => MknodType::CharDevice(dev_id), + }; + dev_path = dev_path.mknod(next_name, mkmod!(a+rw), mknod_type)?; } else { // Create the parent directory dev_path = diff --git a/kernel/src/fs/ext2/impl_for_vfs/inode.rs b/kernel/src/fs/ext2/impl_for_vfs/inode.rs index 3c00195fa..49f5ba4cd 100644 --- a/kernel/src/fs/ext2/impl_for_vfs/inode.rs +++ b/kernel/src/fs/ext2/impl_for_vfs/inode.rs @@ -139,7 +139,7 @@ impl Inode for Ext2Inode { "the device of ID 0 does not exist", ))); } - let device_type = inode_type.as_device_type().unwrap(); + let device_type = inode_type.device_type().unwrap(); let Some(device) = device::lookup(device_type, DeviceId::from_encoded_u64(device_id)) else { @@ -161,14 +161,18 @@ impl Inode for Ext2Inode { } fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result> { - let inode_type = type_.inode_type(); let inode = match type_ { - MknodType::CharDevice(dev) | MknodType::BlockDevice(dev) => { - let inode = self.create(name, inode_type, mode.into())?; - inode.set_device_id(dev.id().as_encoded_u64()).unwrap(); + MknodType::CharDevice(dev) => { + let inode = self.create(name, InodeType::CharDevice, mode.into())?; + inode.set_device_id(dev).unwrap(); inode } - MknodType::NamedPipe => self.create(name, inode_type, mode.into())?, + MknodType::BlockDevice(dev) => { + let inode = self.create(name, InodeType::BlockDevice, mode.into())?; + inode.set_device_id(dev).unwrap(); + inode + } + MknodType::NamedPipe => self.create(name, InodeType::NamedPipe, mode.into())?, }; Ok(inode) diff --git a/kernel/src/fs/ramfs/fs.rs b/kernel/src/fs/ramfs/fs.rs index 758af654e..b8f2ac054 100644 --- a/kernel/src/fs/ramfs/fs.rs +++ b/kernel/src/fs/ramfs/fs.rs @@ -8,6 +8,7 @@ use core::{ use align_ext::AlignExt; use aster_block::bio::BioWaiter; use aster_util::slot_vec::SlotVec; +use device_id::DeviceId; use hashbrown::HashMap; use ostd::{ mm::{io_util::HasVmReaderWriter, HasSize}, @@ -16,8 +17,9 @@ use ostd::{ use super::{memfd::MemfdInode, xattr::RamXattr, *}; use crate::{ + device, fs::{ - device::Device, + device::DeviceType, inode_handle::FileIo, notify::FsEventPublisher, path::{is_dot, is_dot_or_dotdot, is_dotdot}, @@ -127,7 +129,8 @@ enum Inner { Dir(RwLock), File(PageCache), SymLink(SpinLock), - Device(Arc), + BlockDevice(u64), + CharDevice(u64), Socket, NamedPipe(NamedPipe), } @@ -145,8 +148,12 @@ impl Inner { Self::SymLink(SpinLock::new(String::from(""))) } - pub(self) fn new_device(device: Arc) -> Self { - Self::Device(device) + pub(self) fn new_block_device(dev_id: u64) -> Self { + Self::BlockDevice(dev_id) + } + + pub(self) fn new_char_device(dev_id: u64) -> Self { + Self::CharDevice(dev_id) } pub(self) fn new_socket() -> Self { @@ -182,9 +189,17 @@ impl Inner { } } - fn as_device(&self) -> Option<&Arc> { + fn device_id(&self) -> Option { match self { - Self::Device(device) => Some(device), + Self::BlockDevice(dev_id) | Self::CharDevice(dev_id) => Some(*dev_id), + _ => None, + } + } + + fn device_type(&self) -> Option { + match self { + Self::BlockDevice(_) => Some(DeviceType::Block), + Self::CharDevice(_) => Some(DeviceType::Char), _ => None, } } @@ -195,7 +210,26 @@ impl Inner { status_flags: StatusFlags, ) -> Option>> { match self { - Self::Device(device) => Some(device.open()), + Self::BlockDevice(device_id) | Self::CharDevice(device_id) => { + if *device_id == 0 { + return Some(Err(Error::with_message( + Errno::ENODEV, + "the device of ID 0 does not exist", + ))); + } + + let device_type = self.device_type().unwrap(); + let Some(device) = + device::lookup(device_type, DeviceId::from_encoded_u64(*device_id)) + else { + return Some(Err(Error::with_message( + Errno::ENODEV, + "the required device ID does not exist", + ))); + }; + + Some(device.open()) + } Self::NamedPipe(pipe) => Some(pipe.open(access_mode, status_flags)), _ => None, } @@ -480,13 +514,19 @@ impl RamInode { mode: InodeMode, uid: Uid, gid: Gid, - device: Arc, + dev_type: DeviceType, + dev_id: u64, ) -> Arc { + let inner = match dev_type { + DeviceType::Block => Inner::new_block_device(dev_id), + DeviceType::Char => Inner::new_char_device(dev_id), + }; + Arc::new_cyclic(|weak_self| RamInode { - inner: Inner::new_device(device.clone()), + inner, metadata: SpinLock::new(InodeMeta::new(mode, uid, gid)), ino: fs.alloc_id(), - typ: InodeType::from(device.type_()), + typ: dev_type.into(), this: weak_self.clone(), fs: Arc::downgrade(fs), extension: Extension::new(), @@ -733,13 +773,17 @@ impl Inode for RamInode { } let new_inode = match type_ { - MknodType::CharDevice(device) | MknodType::BlockDevice(device) => RamInode::new_device( - &self.fs.upgrade().unwrap(), - mode, - Uid::new_root(), - Gid::new_root(), - device, - ), + MknodType::CharDevice(dev_id) | MknodType::BlockDevice(dev_id) => { + let dev_type = type_.device_type().unwrap(); + RamInode::new_device( + &self.fs.upgrade().unwrap(), + mode, + Uid::new_root(), + Gid::new_root(), + dev_type, + dev_id, + ) + } MknodType::NamedPipe => RamInode::new_named_pipe( &self.fs.upgrade().unwrap(), mode, @@ -1136,11 +1180,7 @@ impl Inode for RamInode { } fn metadata(&self) -> Metadata { - let rdev = self - .inner - .as_device() - .map(|device| device.id().as_encoded_u64()) - .unwrap_or(0); + let rdev = self.inner.device_id().unwrap_or(0); let inode_metadata = self.metadata.lock(); Metadata { dev: 0, diff --git a/kernel/src/fs/utils/inode.rs b/kernel/src/fs/utils/inode.rs index 8208a986f..c189b6e51 100644 --- a/kernel/src/fs/utils/inode.rs +++ b/kernel/src/fs/utils/inode.rs @@ -69,7 +69,7 @@ impl InodeType { .map_err(|_| Error::with_message(Errno::EINVAL, "invalid file type")) } - pub fn as_device_type(&self) -> Option { + pub fn device_type(&self) -> Option { match self { InodeType::BlockDevice => Some(DeviceType::Block), InodeType::CharDevice => Some(DeviceType::Char), @@ -225,27 +225,16 @@ impl Metadata { pub enum MknodType { NamedPipe, - CharDevice(Arc), - BlockDevice(Arc), + CharDevice(u64), + BlockDevice(u64), } impl MknodType { - pub fn inode_type(&self) -> InodeType { + pub fn device_type(&self) -> Option { match self { - MknodType::NamedPipe => InodeType::NamedPipe, - MknodType::CharDevice(_) => InodeType::CharDevice, - MknodType::BlockDevice(_) => InodeType::BlockDevice, - } - } -} - -impl From> for MknodType { - fn from(device: Arc) -> Self { - let inode_type: InodeType = device.type_().into(); - match inode_type { - InodeType::CharDevice => Self::CharDevice(device), - InodeType::BlockDevice => Self::BlockDevice(device), - _ => unreachable!(), + MknodType::NamedPipe => None, + MknodType::CharDevice(_) => Some(DeviceType::Char), + MknodType::BlockDevice(_) => Some(DeviceType::Block), } } } diff --git a/kernel/src/syscall/mknod.rs b/kernel/src/syscall/mknod.rs index bb54ccaf4..000e21da9 100644 --- a/kernel/src/syscall/mknod.rs +++ b/kernel/src/syscall/mknod.rs @@ -1,10 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 -use device_id::DeviceId; - use super::SyscallReturn; use crate::{ - device, fs::{ self, file_table::FileDesc, @@ -48,11 +45,11 @@ pub fn sys_mknodat( InodeType::File => { let _ = dir_path.new_fs_child(&name, InodeType::File, inode_mode)?; } - InodeType::CharDevice | InodeType::BlockDevice => { - let device_type = inode_type.as_device_type().unwrap(); - let device_inode = device::lookup(device_type, DeviceId::from_encoded_u64(dev as u64)) - .ok_or_else(|| Error::new(Errno::ENODEV))?; - let _ = dir_path.mknod(&name, inode_mode, device_inode.into())?; + InodeType::CharDevice => { + let _ = dir_path.mknod(&name, inode_mode, MknodType::CharDevice(dev as u64))?; + } + InodeType::BlockDevice => { + let _ = dir_path.mknod(&name, inode_mode, MknodType::BlockDevice(dev as u64))?; } InodeType::NamedPipe => { let _ = dir_path.mknod(&name, inode_mode, MknodType::NamedPipe)?;