feat: 添加gendisk抽象 (#903)

* feat: 添加gendisk抽象.

* 支持使用virtio磁盘作为根文件系统

* Update initial_kthread.rs to resolve conflict.

---------

Co-authored-by: Donkey Kane <109840258+xiaolin2004@users.noreply.github.com>
This commit is contained in:
LoGin
2024-09-02 23:37:55 +08:00
committed by GitHub
parent 232570ae98
commit 9fa0e95eee
17 changed files with 979 additions and 287 deletions

View File

@ -5,17 +5,19 @@ use alloc::{
sync::{Arc, Weak},
vec::Vec,
};
use log::{debug, error};
use bitmap::traits::BitMapOps;
use log::error;
use system_error::SystemError;
use unified_init::macros::unified_init;
use virtio_drivers::device::blk::VirtIOBlk;
use virtio_drivers::device::blk::{VirtIOBlk, SECTOR_SIZE};
use crate::{
driver::{
base::{
block::{
block_device::{BlockDevice, BlockId, LBA_SIZE},
block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
disk_info::Partition,
manager::{block_dev_manager, BlockDevMeta},
},
class::Class,
device::{
@ -64,18 +66,82 @@ pub fn virtio_blk_0() -> Option<Arc<VirtIOBlkDevice>> {
pub fn virtio_blk(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
let device = VirtIOBlkDevice::new(transport, dev_id);
if let Some(device) = device {
debug!("VirtIOBlkDevice '{:?}' created", device.dev_id);
virtio_device_manager()
.device_add(device.clone() as Arc<dyn VirtIODevice>)
.expect("Add virtio blk failed");
}
}
static mut VIRTIOBLK_MANAGER: Option<VirtIOBlkManager> = None;
#[inline]
fn virtioblk_manager() -> &'static VirtIOBlkManager {
unsafe { VIRTIOBLK_MANAGER.as_ref().unwrap() }
}
#[unified_init(INITCALL_POSTCORE)]
fn virtioblk_manager_init() -> Result<(), SystemError> {
unsafe {
VIRTIOBLK_MANAGER = Some(VirtIOBlkManager::new());
}
Ok(())
}
pub struct VirtIOBlkManager {
inner: SpinLock<InnerVirtIOBlkManager>,
}
struct InnerVirtIOBlkManager {
id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
devname: [Option<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
}
impl VirtIOBlkManager {
pub const MAX_DEVICES: usize = 25;
pub fn new() -> Self {
Self {
inner: SpinLock::new(InnerVirtIOBlkManager {
id_bmp: bitmap::StaticBitmap::new(),
devname: [const { None }; Self::MAX_DEVICES],
}),
}
}
fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkManager> {
self.inner.lock()
}
pub fn alloc_id(&self) -> Option<BlockDevName> {
let mut inner = self.inner();
let idx = inner.id_bmp.first_false_index()?;
inner.id_bmp.set(idx, true);
let name = Self::format_name(idx);
inner.devname[idx] = Some(name.clone());
Some(name)
}
/// Generate a new block device name like 'vda', 'vdb', etc.
fn format_name(id: usize) -> BlockDevName {
let x = (b'a' + id as u8) as char;
BlockDevName::new(format!("vd{}", x), id)
}
pub fn free_id(&self, id: usize) {
if id >= Self::MAX_DEVICES {
return;
}
self.inner().id_bmp.set(id, false);
self.inner().devname[id] = None;
}
}
/// virtio block device
#[derive(Debug)]
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtIOBlkDevice {
blkdev_meta: BlockDevMeta,
dev_id: Arc<DeviceId>,
inner: SpinLock<InnerVirtIOBlkDevice>,
locked_kobj_state: LockedKObjectState,
@ -87,6 +153,7 @@ unsafe impl Sync for VirtIOBlkDevice {}
impl VirtIOBlkDevice {
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
let devname = virtioblk_manager().alloc_id()?;
let irq = transport.irq().map(|irq| IrqNumber::new(irq.data()));
let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
if let Err(e) = device_inner {
@ -97,6 +164,7 @@ impl VirtIOBlkDevice {
let mut device_inner: VirtIOBlk<HalImpl, VirtIOTransport> = device_inner.unwrap();
device_inner.enable_interrupts();
let dev = Arc::new_cyclic(|self_ref| Self {
blkdev_meta: BlockDevMeta::new(devname),
self_ref: self_ref.clone(),
dev_id,
locked_kobj_state: LockedKObjectState::default(),
@ -123,6 +191,26 @@ impl VirtIOBlkDevice {
}
impl BlockDevice for VirtIOBlkDevice {
fn dev_name(&self) -> &BlockDevName {
&self.blkdev_meta.devname
}
fn blkdev_meta(&self) -> &BlockDevMeta {
&self.blkdev_meta
}
fn disk_range(&self) -> GeneralBlockRange {
let inner = self.inner();
let blocks = inner.device_inner.capacity() as usize * SECTOR_SIZE / LBA_SIZE;
drop(inner);
log::debug!(
"VirtIOBlkDevice '{:?}' disk_range: 0..{}",
self.dev_name(),
blocks
);
GeneralBlockRange::new(0, blocks).unwrap()
}
fn read_at_sync(
&self,
lba_id_start: BlockId,
@ -411,7 +499,7 @@ struct InnerVirtIOBlkDriver {
impl VirtIODriver for VirtIOBlkDriver {
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
let _dev = device
let dev = device
.clone()
.arc_any()
.downcast::<VirtIOBlkDevice>()
@ -423,6 +511,7 @@ impl VirtIODriver for VirtIOBlkDriver {
SystemError::EINVAL
})?;
block_dev_manager().register(dev as Arc<dyn BlockDevice>)?;
return Ok(());
}
}