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

128 lines
3.5 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
//! The block devices of Asterinas.
2023-09-18 03:47:17 +00:00
//
//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
2024-06-28 10:45:16 +00:00
//! safe and convenient block I/O operations, for example:
2023-09-18 03:47:17 +00:00
//!
//! ```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)]
2023-09-18 03:47:17 +00:00
#![feature(step_trait)]
#![feature(trait_upcasting)]
2023-09-18 03:47:17 +00:00
#![allow(dead_code)]
extern crate alloc;
2023-09-18 03:47:17 +00:00
pub mod bio;
pub mod id;
mod impl_block_device;
mod prelude;
pub mod request_queue;
use component::{init_component, ComponentInitError};
2024-06-19 08:18:39 +00:00
use ostd::sync::SpinLock;
use spin::Once;
use self::{
bio::{BioEnqueueError, SubmittedBio},
prelude::*,
};
2024-06-19 08:18:39 +00:00
pub const BLOCK_SIZE: usize = ostd::mm::PAGE_SIZE;
2023-09-18 03:47:17 +00:00
pub const SECTOR_SIZE: usize = 512;
2023-08-28 07:03:28 +00:00
pub trait BlockDevice: Send + Sync + Any + Debug {
2024-01-25 07:00:19 +00:00
/// Enqueues a new `SubmittedBio` to the block device.
fn enqueue(&self, bio: SubmittedBio) -> Result<(), BioEnqueueError>;
2024-07-18 11:45:38 +00:00
/// Returns the metadata of the block device.
fn metadata(&self) -> BlockDeviceMeta;
}
/// Metadata for a block device.
#[derive(Debug, Clone, Copy)]
pub struct BlockDeviceMeta {
/// The upper limit for the number of segments per bio.
pub max_nr_segments_per_bio: usize,
/// The total number of sectors of the block device.
pub nr_sectors: usize,
// Additional useful metadata can be added here in the future.
}
2023-09-18 03:47:17 +00:00
impl dyn BlockDevice {
pub fn downcast_ref<T: BlockDevice>(&self) -> Option<&T> {
(self as &dyn Any).downcast_ref::<T>()
}
}
2023-08-28 07:03:28 +00:00
pub fn register_device(name: String, device: Arc<dyn BlockDevice>) {
2023-11-20 12:37:51 +00:00
COMPONENT
.get()
.unwrap()
.block_device_table
.lock()
.insert(name, device);
}
2023-11-20 12:37:51 +00:00
pub fn get_device(str: &str) -> Option<Arc<dyn BlockDevice>> {
COMPONENT
.get()
.unwrap()
.block_device_table
.lock()
.get(str)
.cloned()
}
2023-08-28 07:03:28 +00:00
pub fn all_devices() -> Vec<(String, Arc<dyn BlockDevice>)> {
2023-11-20 12:37:51 +00:00
let block_devs = COMPONENT.get().unwrap().block_device_table.lock();
block_devs
.iter()
.map(|(name, device)| (name.clone(), device.clone()))
.collect()
2023-08-28 07:03:28 +00:00
}
2023-08-28 07:03:28 +00:00
static COMPONENT: Once<Component> = Once::new();
#[init_component]
fn component_init() -> Result<(), ComponentInitError> {
let a = Component::init()?;
COMPONENT.call_once(|| a);
Ok(())
}
2023-08-28 07:03:28 +00:00
#[derive(Debug)]
struct Component {
2023-11-20 12:37:51 +00:00
block_device_table: SpinLock<BTreeMap<String, Arc<dyn BlockDevice>>>,
2023-08-28 07:03:28 +00:00
}
impl Component {
pub fn init() -> Result<Self, ComponentInitError> {
Ok(Self {
2023-11-20 12:37:51 +00:00
block_device_table: SpinLock::new(BTreeMap::new()),
2023-08-28 07:03:28 +00:00
})
}
}