mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 16:33:24 +00:00
Revise the BlockDevice
trait
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
e83e1fc01b
commit
ff525112d0
@ -19,7 +19,7 @@ mod test {
|
||||
|
||||
use aster_block::{
|
||||
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
||||
BlockDevice,
|
||||
BlockDevice, BlockDeviceMeta,
|
||||
};
|
||||
use ostd::{
|
||||
mm::{FrameAllocOptions, Segment, VmIo},
|
||||
@ -99,8 +99,11 @@ mod test {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn max_nr_segments_per_bio(&self) -> usize {
|
||||
usize::MAX
|
||||
fn metadata(&self) -> BlockDeviceMeta {
|
||||
BlockDeviceMeta {
|
||||
max_nr_segments_per_bio: usize::MAX,
|
||||
nr_sectors: self.sectors_count(),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Exfat disk image
|
||||
|
@ -36,7 +36,11 @@ impl Ext2 {
|
||||
let raw_super_block = block_device.read_val::<RawSuperBlock>(SUPER_BLOCK_OFFSET)?;
|
||||
SuperBlock::try_from(raw_super_block)?
|
||||
};
|
||||
assert!(super_block.block_size() == BLOCK_SIZE);
|
||||
assert_eq!(
|
||||
super_block.block_size(),
|
||||
BLOCK_SIZE,
|
||||
"currently only support 4096-byte block size"
|
||||
);
|
||||
|
||||
let group_descriptors_segment = {
|
||||
let npages = ((super_block.block_groups_count() as usize)
|
||||
|
@ -56,8 +56,19 @@ 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>;
|
||||
/// Returns the upper limit for the number of segments per bio.
|
||||
fn max_nr_segments_per_bio(&self) -> usize;
|
||||
|
||||
/// 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.
|
||||
}
|
||||
|
||||
impl dyn BlockDevice {
|
||||
|
@ -6,6 +6,7 @@ use core::{fmt::Debug, hint::spin_loop, mem::size_of};
|
||||
use aster_block::{
|
||||
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
||||
request_queue::{BioRequest, BioRequestSingleQueue},
|
||||
BlockDeviceMeta,
|
||||
};
|
||||
use aster_util::safe_ptr::SafePtr;
|
||||
use id_alloc::IdAlloc;
|
||||
@ -79,8 +80,12 @@ impl aster_block::BlockDevice for BlockDevice {
|
||||
self.queue.enqueue(bio)
|
||||
}
|
||||
|
||||
fn max_nr_segments_per_bio(&self) -> usize {
|
||||
self.queue.max_nr_segments_per_bio()
|
||||
fn metadata(&self) -> BlockDeviceMeta {
|
||||
let device_config = self.device.config.read().unwrap();
|
||||
BlockDeviceMeta {
|
||||
max_nr_segments_per_bio: self.queue.max_nr_segments_per_bio(),
|
||||
nr_sectors: device_config.capacity_sectors(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,6 +106,11 @@ impl DeviceInner {
|
||||
/// Creates and inits the device.
|
||||
pub fn init(mut transport: Box<dyn VirtioTransport>) -> Result<Arc<Self>, VirtioDeviceError> {
|
||||
let config = VirtioBlockConfig::new(transport.as_mut());
|
||||
assert_eq!(
|
||||
config.read().unwrap().block_size(),
|
||||
VirtioBlockConfig::sector_size(),
|
||||
"currently not support customized device logical block size"
|
||||
);
|
||||
let num_queues = transport.num_queues();
|
||||
if num_queues != 1 {
|
||||
return Err(VirtioDeviceError::QueuesAmountDoNotMatch(num_queues, 1));
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
pub mod device;
|
||||
|
||||
use aster_block::SECTOR_SIZE;
|
||||
use aster_util::safe_ptr::SafePtr;
|
||||
use bitflags::bitflags;
|
||||
use int_to_c_enum::TryFromInt;
|
||||
@ -56,18 +57,32 @@ pub enum RespStatus {
|
||||
#[derive(Debug, Copy, Clone, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct VirtioBlockConfig {
|
||||
/// The number of 512-byte sectors.
|
||||
capacity: u64,
|
||||
/// The maximum segment size.
|
||||
size_max: u64,
|
||||
/// The geometry of the device.
|
||||
geometry: VirtioBlockGeometry,
|
||||
/// The block size. If `logical_block_size` is not given in qemu cmdline,
|
||||
/// `blk_size` will be set to sector size (512 bytes) by default.
|
||||
blk_size: u32,
|
||||
/// The topology of the device.
|
||||
topology: VirtioBlockTopology,
|
||||
/// Writeback mode.
|
||||
writeback: u8,
|
||||
unused0: [u8; 3],
|
||||
/// The maximum discard sectors for one segment.
|
||||
max_discard_sectors: u32,
|
||||
/// The maximum number of discard segments in a discard command.
|
||||
max_discard_seg: u32,
|
||||
/// Discard commands must be aligned to this number of sectors.
|
||||
discard_sector_alignment: u32,
|
||||
/// The maximum number of write zeroes sectors in one segment.
|
||||
max_write_zeroes_sectors: u32,
|
||||
/// The maximum number of segments in a write zeroes command.
|
||||
max_write_zeroes_seg: u32,
|
||||
/// Set if a write zeroes command may result in the
|
||||
/// deallocation of one or more of the sectors.
|
||||
write_zeros_may_unmap: u8,
|
||||
unused1: [u8; 3],
|
||||
}
|
||||
@ -83,9 +98,13 @@ pub struct VirtioBlockGeometry {
|
||||
#[derive(Debug, Copy, Clone, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct VirtioBlockTopology {
|
||||
/// Exponent for physical block per logical block.
|
||||
physical_block_exp: u8,
|
||||
/// Alignment offset in logical blocks.
|
||||
alignment_offset: u8,
|
||||
/// Minimum I/O size without performance penalty in logical blocks.
|
||||
min_io_size: u16,
|
||||
/// Optimal sustained I/O size in logical blocks.
|
||||
opt_io_size: u32,
|
||||
}
|
||||
|
||||
@ -94,4 +113,20 @@ impl VirtioBlockConfig {
|
||||
let memory = transport.device_config_memory();
|
||||
SafePtr::new(memory, 0)
|
||||
}
|
||||
|
||||
pub(self) const fn sector_size() -> usize {
|
||||
SECTOR_SIZE
|
||||
}
|
||||
|
||||
pub(self) fn block_size(&self) -> usize {
|
||||
self.blk_size as usize
|
||||
}
|
||||
|
||||
pub(self) fn capacity_sectors(&self) -> usize {
|
||||
self.capacity as usize
|
||||
}
|
||||
|
||||
pub(self) fn capacity_bytes(&self) -> usize {
|
||||
self.capacity_sectors() * Self::sector_size()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user