Revise the BlockDevice trait

This commit is contained in:
Shaowei Song
2024-07-18 11:45:38 +00:00
committed by Tate, Hongliang Tian
parent e83e1fc01b
commit ff525112d0
5 changed files with 71 additions and 8 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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));

View File

@ -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()
}
}