mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-26 19:23:23 +00:00
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:
@ -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(());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user