Support looking up block devices

This commit is contained in:
jiangjianfeng 2025-12-04 07:20:46 +00:00 committed by Tate, Hongliang Tian
parent e4a09f5503
commit d8a4b3076f
7 changed files with 64 additions and 20 deletions

View File

@ -9,12 +9,12 @@ mod registry;
mod shm;
pub mod tty;
use device_id::DeviceId;
pub use mem::{getrandom, geturandom};
pub use pty::{new_pty_pair, PtyMaster, PtySlave};
pub use registry::lookup;
use crate::{
fs::{device::Device, fs_resolver::FsPath, path::PerMountFlags, ramfs::RamFs},
fs::{fs_resolver::FsPath, path::PerMountFlags, ramfs::RamFs},
prelude::*,
};
@ -42,11 +42,3 @@ pub fn init_in_first_process(ctx: &Context) -> Result<()> {
Ok(())
}
/// Looks up a device according to the device ID.
pub fn get_device(devid: DeviceId) -> Result<Arc<dyn Device>> {
// TODO: Add support for looking up block devices.
registry::char::lookup(devid).ok_or_else(|| {
Error::with_message(Errno::EINVAL, "the device ID is invalid or unsupported")
})
}

View File

@ -127,3 +127,18 @@ impl FileIo for OpenBlockFile {
true
}
}
pub(super) fn lookup(id: DeviceId) -> Option<Arc<dyn Device>> {
let block_device = aster_block::lookup(id)?;
let mut registry = DEVICE_REGISTRY.lock();
let block_device_file = registry
.entry(id.to_raw())
.or_insert_with(move || Arc::new(BlockFile::new(block_device)))
.clone();
Some(block_device_file)
}
// TODO: Merge the two mapping tables, one is here and the other is in the block component.
// Maintaining two mapping tables is undesirable due to duplication and (potential) inconsistency.
static DEVICE_REGISTRY: Mutex<BTreeMap<u32, Arc<dyn Device>>> = Mutex::new(BTreeMap::new());

View File

@ -42,7 +42,7 @@ pub fn collect_all() -> Vec<Arc<dyn Device>> {
}
/// Looks up a char device of a given device ID.
pub fn lookup(id: DeviceId) -> Option<Arc<dyn Device>> {
pub(super) fn lookup(id: DeviceId) -> Option<Arc<dyn Device>> {
DEVICE_REGISTRY.lock().get(&id.to_raw()).cloned()
}

View File

@ -1,6 +1,14 @@
// SPDX-License-Identifier: MPL-2.0
use crate::{fs::fs_resolver::FsResolver, prelude::*};
use device_id::DeviceId;
use crate::{
fs::{
device::{Device, DeviceType},
fs_resolver::FsResolver,
},
prelude::*,
};
mod block;
pub(super) mod char;
@ -15,3 +23,10 @@ pub(super) fn init_in_first_process(fs_resolver: &FsResolver) -> Result<()> {
Ok(())
}
pub fn lookup(device_type: DeviceType, device_id: DeviceId) -> Option<Arc<dyn Device>> {
match device_type {
DeviceType::Char => char::lookup(device_id),
DeviceType::Block => block::lookup(device_id),
}
}

View File

@ -5,7 +5,7 @@ use core::time::Duration;
use device_id::DeviceId;
use crate::{
device::get_device,
device,
fs::{
ext2::{FilePerm, Inode as Ext2Inode},
inode_handle::FileIo,
@ -131,12 +131,24 @@ impl Inode for Ext2Inode {
status_flags: StatusFlags,
) -> Option<Result<Box<dyn FileIo>>> {
match self.inode_type() {
InodeType::BlockDevice | InodeType::CharDevice => {
inode_type @ (InodeType::BlockDevice | InodeType::CharDevice) => {
let device_id = self.device_id();
let device = match get_device(DeviceId::from_encoded_u64(device_id)) {
Ok(device) => device,
Err(e) => return Some(Err(e)),
if device_id == 0 {
return Some(Err(Error::with_message(
Errno::ENODEV,
"the device of ID 0 does not exist",
)));
}
let device_type = inode_type.as_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())
}
InodeType::NamedPipe => Some(self.open_named_pipe(access_mode, status_flags)),

View File

@ -68,6 +68,14 @@ impl InodeType {
Self::try_from(mode & TYPE_MASK)
.map_err(|_| Error::with_message(Errno::EINVAL, "invalid file type"))
}
pub fn as_device_type(&self) -> Option<DeviceType> {
match self {
InodeType::BlockDevice => Some(DeviceType::Block),
InodeType::CharDevice => Some(DeviceType::Char),
_ => None,
}
}
}
impl From<DeviceType> for InodeType {

View File

@ -4,9 +4,9 @@ use device_id::DeviceId;
use super::SyscallReturn;
use crate::{
device::get_device,
fs,
device,
fs::{
self,
file_table::FileDesc,
fs_resolver::{FsPath, AT_FDCWD},
utils::{InodeMode, InodeType, MknodType},
@ -49,7 +49,9 @@ pub fn sys_mknodat(
let _ = dir_path.new_fs_child(&name, InodeType::File, inode_mode)?;
}
InodeType::CharDevice | InodeType::BlockDevice => {
let device_inode = get_device(DeviceId::from_encoded_u64(dev as u64))?;
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::NamedPipe => {