Make device Inode behave like pointer

This commit is contained in:
jiangjianfeng 2025-12-04 08:17:27 +00:00 committed by Tate, Hongliang Tian
parent d8a4b3076f
commit 83c158e3b5
7 changed files with 101 additions and 60 deletions

View File

@ -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)?;
}
}

View File

@ -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)?;
}
}

View File

@ -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<dyn Device>, path: &str, fs_resolver: &FsResolver) -> Result<Path> {
pub fn add_node(
dev_type: DeviceType,
dev_id: u64,
path: &str,
fs_resolver: &FsResolver,
) -> Result<Path> {
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<dyn Device>, 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 =

View File

@ -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<Arc<dyn Inode>> {
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)

View File

@ -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<DirEntry>),
File(PageCache),
SymLink(SpinLock<String>),
Device(Arc<dyn Device>),
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<dyn Device>) -> 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<dyn Device>> {
fn device_id(&self) -> Option<u64> {
match self {
Self::Device(device) => Some(device),
Self::BlockDevice(dev_id) | Self::CharDevice(dev_id) => Some(*dev_id),
_ => None,
}
}
fn device_type(&self) -> Option<DeviceType> {
match self {
Self::BlockDevice(_) => Some(DeviceType::Block),
Self::CharDevice(_) => Some(DeviceType::Char),
_ => None,
}
}
@ -195,7 +210,26 @@ impl Inner {
status_flags: StatusFlags,
) -> Option<Result<Box<dyn FileIo>>> {
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<dyn Device>,
dev_type: DeviceType,
dev_id: u64,
) -> Arc<Self> {
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,

View File

@ -69,7 +69,7 @@ impl InodeType {
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid file type"))
}
pub fn as_device_type(&self) -> Option<DeviceType> {
pub fn device_type(&self) -> Option<DeviceType> {
match self {
InodeType::BlockDevice => Some(DeviceType::Block),
InodeType::CharDevice => Some(DeviceType::Char),
@ -225,27 +225,16 @@ impl Metadata {
pub enum MknodType {
NamedPipe,
CharDevice(Arc<dyn Device>),
BlockDevice(Arc<dyn Device>),
CharDevice(u64),
BlockDevice(u64),
}
impl MknodType {
pub fn inode_type(&self) -> InodeType {
pub fn device_type(&self) -> Option<DeviceType> {
match self {
MknodType::NamedPipe => InodeType::NamedPipe,
MknodType::CharDevice(_) => InodeType::CharDevice,
MknodType::BlockDevice(_) => InodeType::BlockDevice,
}
}
}
impl From<Arc<dyn Device>> for MknodType {
fn from(device: Arc<dyn Device>) -> 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),
}
}
}

View File

@ -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)?;