asterinas/kernel/comps/block/src/lib.rs

114 lines
3.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: MPL-2.0
//! The block devices of Asterinas.
//
//This crate provides a number of base components for block devices, including
//! an abstraction of block devices, as well as the registration and lookup of block devices.
//!
//! Block devices use a queue-based model for asynchronous I/O operations. It is necessary
//! for a block device to maintain a queue to handle I/O requests. The users (e.g., fs)
//! submit I/O requests to this queue and wait for their completion. Drivers implementing
//! block devices can create their own queues as needed, with the possibility to reorder
//! and merge requests within the queue.
//!
//! This crate also offers the `Bio` related data structures and APIs to accomplish
//! safe and convenient block I/O operations, for exmaple:
//!
//! ```no_run
//! // Creates a bio request.
//! let bio = Bio::new(BioType::Write, sid, segments, None);
//! // Submits to the block device.
//! let bio_waiter = bio.submit(block_device)?;
//! // Waits for the the completion.
//! let Some(status) = bio_waiter.wait() else {
//! return Err(IoError);
//! };
//! assert!(status == BioStatus::Complete);
//! ```
//!
#![no_std]
#![deny(unsafe_code)]
#![feature(fn_traits)]
#![feature(step_trait)]
#![allow(dead_code)]
extern crate alloc;
pub mod bio;
pub mod id;
mod impl_block_device;
mod prelude;
pub mod request_queue;
use aster_frame::sync::SpinLock;
use component::{init_component, ComponentInitError};
use spin::Once;
use self::{
bio::{BioEnqueueError, SubmittedBio},
prelude::*,
};
pub const BLOCK_SIZE: usize = aster_frame::vm::PAGE_SIZE;
pub const SECTOR_SIZE: usize = 512;
pub trait BlockDevice: Send + Sync + Any + Debug {
/// Enqueues a new `SubmittedBio` to the block device.
fn enqueue(&self, bio: SubmittedBio) -> Result<(), BioEnqueueError>;
}
impl dyn BlockDevice {
pub fn downcast_ref<T: BlockDevice>(&self) -> Option<&T> {
(self as &dyn Any).downcast_ref::<T>()
}
}
pub fn register_device(name: String, device: Arc<dyn BlockDevice>) {
COMPONENT
.get()
.unwrap()
.block_device_table
.lock()
.insert(name, device);
}
pub fn get_device(str: &str) -> Option<Arc<dyn BlockDevice>> {
COMPONENT
.get()
.unwrap()
.block_device_table
.lock()
.get(str)
.cloned()
}
pub fn all_devices() -> Vec<(String, Arc<dyn BlockDevice>)> {
let block_devs = COMPONENT.get().unwrap().block_device_table.lock();
block_devs
.iter()
.map(|(name, device)| (name.clone(), device.clone()))
.collect()
}
static COMPONENT: Once<Component> = Once::new();
#[init_component]
fn component_init() -> Result<(), ComponentInitError> {
let a = Component::init()?;
COMPONENT.call_once(|| a);
Ok(())
}
#[derive(Debug)]
struct Component {
block_device_table: SpinLock<BTreeMap<String, Arc<dyn BlockDevice>>>,
}
impl Component {
pub fn init() -> Result<Self, ComponentInitError> {
Ok(Self {
block_device_table: SpinLock::new(BTreeMap::new()),
})
}
}