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::{
|
use aster_block::{
|
||||||
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
||||||
BlockDevice,
|
BlockDevice, BlockDeviceMeta,
|
||||||
};
|
};
|
||||||
use ostd::{
|
use ostd::{
|
||||||
mm::{FrameAllocOptions, Segment, VmIo},
|
mm::{FrameAllocOptions, Segment, VmIo},
|
||||||
@ -99,8 +99,11 @@ mod test {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max_nr_segments_per_bio(&self) -> usize {
|
fn metadata(&self) -> BlockDeviceMeta {
|
||||||
usize::MAX
|
BlockDeviceMeta {
|
||||||
|
max_nr_segments_per_bio: usize::MAX,
|
||||||
|
nr_sectors: self.sectors_count(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Exfat disk image
|
/// Exfat disk image
|
||||||
|
@ -36,7 +36,11 @@ impl Ext2 {
|
|||||||
let raw_super_block = block_device.read_val::<RawSuperBlock>(SUPER_BLOCK_OFFSET)?;
|
let raw_super_block = block_device.read_val::<RawSuperBlock>(SUPER_BLOCK_OFFSET)?;
|
||||||
SuperBlock::try_from(raw_super_block)?
|
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 group_descriptors_segment = {
|
||||||
let npages = ((super_block.block_groups_count() as usize)
|
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 {
|
pub trait BlockDevice: Send + Sync + Any + Debug {
|
||||||
/// Enqueues a new `SubmittedBio` to the block device.
|
/// Enqueues a new `SubmittedBio` to the block device.
|
||||||
fn enqueue(&self, bio: SubmittedBio) -> Result<(), BioEnqueueError>;
|
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 {
|
impl dyn BlockDevice {
|
||||||
|
@ -6,6 +6,7 @@ use core::{fmt::Debug, hint::spin_loop, mem::size_of};
|
|||||||
use aster_block::{
|
use aster_block::{
|
||||||
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
||||||
request_queue::{BioRequest, BioRequestSingleQueue},
|
request_queue::{BioRequest, BioRequestSingleQueue},
|
||||||
|
BlockDeviceMeta,
|
||||||
};
|
};
|
||||||
use aster_util::safe_ptr::SafePtr;
|
use aster_util::safe_ptr::SafePtr;
|
||||||
use id_alloc::IdAlloc;
|
use id_alloc::IdAlloc;
|
||||||
@ -79,8 +80,12 @@ impl aster_block::BlockDevice for BlockDevice {
|
|||||||
self.queue.enqueue(bio)
|
self.queue.enqueue(bio)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max_nr_segments_per_bio(&self) -> usize {
|
fn metadata(&self) -> BlockDeviceMeta {
|
||||||
self.queue.max_nr_segments_per_bio()
|
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.
|
/// Creates and inits the device.
|
||||||
pub fn init(mut transport: Box<dyn VirtioTransport>) -> Result<Arc<Self>, VirtioDeviceError> {
|
pub fn init(mut transport: Box<dyn VirtioTransport>) -> Result<Arc<Self>, VirtioDeviceError> {
|
||||||
let config = VirtioBlockConfig::new(transport.as_mut());
|
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();
|
let num_queues = transport.num_queues();
|
||||||
if num_queues != 1 {
|
if num_queues != 1 {
|
||||||
return Err(VirtioDeviceError::QueuesAmountDoNotMatch(num_queues, 1));
|
return Err(VirtioDeviceError::QueuesAmountDoNotMatch(num_queues, 1));
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
pub mod device;
|
pub mod device;
|
||||||
|
|
||||||
|
use aster_block::SECTOR_SIZE;
|
||||||
use aster_util::safe_ptr::SafePtr;
|
use aster_util::safe_ptr::SafePtr;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use int_to_c_enum::TryFromInt;
|
use int_to_c_enum::TryFromInt;
|
||||||
@ -56,18 +57,32 @@ pub enum RespStatus {
|
|||||||
#[derive(Debug, Copy, Clone, Pod)]
|
#[derive(Debug, Copy, Clone, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VirtioBlockConfig {
|
pub struct VirtioBlockConfig {
|
||||||
|
/// The number of 512-byte sectors.
|
||||||
capacity: u64,
|
capacity: u64,
|
||||||
|
/// The maximum segment size.
|
||||||
size_max: u64,
|
size_max: u64,
|
||||||
|
/// The geometry of the device.
|
||||||
geometry: VirtioBlockGeometry,
|
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,
|
blk_size: u32,
|
||||||
|
/// The topology of the device.
|
||||||
topology: VirtioBlockTopology,
|
topology: VirtioBlockTopology,
|
||||||
|
/// Writeback mode.
|
||||||
writeback: u8,
|
writeback: u8,
|
||||||
unused0: [u8; 3],
|
unused0: [u8; 3],
|
||||||
|
/// The maximum discard sectors for one segment.
|
||||||
max_discard_sectors: u32,
|
max_discard_sectors: u32,
|
||||||
|
/// The maximum number of discard segments in a discard command.
|
||||||
max_discard_seg: u32,
|
max_discard_seg: u32,
|
||||||
|
/// Discard commands must be aligned to this number of sectors.
|
||||||
discard_sector_alignment: u32,
|
discard_sector_alignment: u32,
|
||||||
|
/// The maximum number of write zeroes sectors in one segment.
|
||||||
max_write_zeroes_sectors: u32,
|
max_write_zeroes_sectors: u32,
|
||||||
|
/// The maximum number of segments in a write zeroes command.
|
||||||
max_write_zeroes_seg: u32,
|
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,
|
write_zeros_may_unmap: u8,
|
||||||
unused1: [u8; 3],
|
unused1: [u8; 3],
|
||||||
}
|
}
|
||||||
@ -83,9 +98,13 @@ pub struct VirtioBlockGeometry {
|
|||||||
#[derive(Debug, Copy, Clone, Pod)]
|
#[derive(Debug, Copy, Clone, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VirtioBlockTopology {
|
pub struct VirtioBlockTopology {
|
||||||
|
/// Exponent for physical block per logical block.
|
||||||
physical_block_exp: u8,
|
physical_block_exp: u8,
|
||||||
|
/// Alignment offset in logical blocks.
|
||||||
alignment_offset: u8,
|
alignment_offset: u8,
|
||||||
|
/// Minimum I/O size without performance penalty in logical blocks.
|
||||||
min_io_size: u16,
|
min_io_size: u16,
|
||||||
|
/// Optimal sustained I/O size in logical blocks.
|
||||||
opt_io_size: u32,
|
opt_io_size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,4 +113,20 @@ impl VirtioBlockConfig {
|
|||||||
let memory = transport.device_config_memory();
|
let memory = transport.device_config_memory();
|
||||||
SafePtr::new(memory, 0)
|
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