Skip to content

Commit

Permalink
feat: 添加gendisk抽象 (#903)
Browse files Browse the repository at this point in the history
* feat: 添加gendisk抽象.

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

* Update initial_kthread.rs to resolve conflict.

---------

Co-authored-by: Donkey Kane <109840258+xiaolin2004@users.noreply.github.com>
  • Loading branch information
fslongjin and xiaolin2004 authored Sep 2, 2024
1 parent 232570a commit 9fa0e95
Show file tree
Hide file tree
Showing 17 changed files with 980 additions and 288 deletions.
118 changes: 115 additions & 3 deletions kernel/src/driver/base/block/block_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ use crate::driver::{
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
};

use alloc::{sync::Arc, vec::Vec};
use core::any::Any;
use alloc::{string::String, sync::Arc, vec::Vec};
use core::{any::Any, fmt::Display, ops::Deref};
use log::error;
use system_error::SystemError;

use super::disk_info::Partition;
use super::{disk_info::Partition, gendisk::GenDisk, manager::BlockDevMeta};

/// 该文件定义了 Device 和 BlockDevice 的接口
/// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示,而不是自己定义错误enum
Expand All @@ -36,6 +36,41 @@ pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超
/// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA)
pub const LBA_SIZE: usize = 512;

#[derive(Debug, Clone, Copy)]
pub struct GeneralBlockRange {
pub lba_start: usize,
pub lba_end: usize,
}

impl GeneralBlockRange {
pub fn new(lba_start: usize, lba_end: usize) -> Option<Self> {
if lba_start >= lba_end {
return None;
}
return Some(GeneralBlockRange { lba_start, lba_end });
}

#[inline]
pub fn len(&self) -> usize {
return self.lba_end - self.lba_start;
}

/// 取交集
pub fn intersects_with(&self, rhs: &Self) -> Option<Self> {
// 检查是否相交
if self.lba_start <= rhs.lba_end && self.lba_end >= rhs.lba_start {
// 计算相交部分的起始和结束 LBA
let start = usize::max(self.lba_start, rhs.lba_start);
let end = usize::min(self.lba_end, rhs.lba_end);
// 返回相交部分
GeneralBlockRange::new(start, end)
} else {
// 不相交,返回 None
None
}
}
}

/// @brief 块设备的迭代器
/// @usage 某次操作读/写块设备的[L,R]范围内的字节,
/// 那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange
Expand Down Expand Up @@ -186,8 +221,80 @@ pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
return lba_id * blk_size;
}

/// 块设备的名字
pub struct BlockDevName {
name: Arc<String>,
id: usize,
}

impl BlockDevName {
pub fn new(name: String, id: usize) -> Self {
return BlockDevName {
name: Arc::new(name),
id,
};
}

#[inline]
pub fn id(&self) -> usize {
return self.id;
}
}

impl core::fmt::Debug for BlockDevName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return write!(f, "{}", self.name);
}
}

impl Display for BlockDevName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
return write!(f, "{}", self.name);
}
}

impl Clone for BlockDevName {
fn clone(&self) -> Self {
return BlockDevName {
name: self.name.clone(),
id: self.id,
};
}
}

impl core::hash::Hash for BlockDevName {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}

impl Deref for BlockDevName {
type Target = String;

fn deref(&self) -> &Self::Target {
return self.name.as_ref();
}
}

impl PartialEq for BlockDevName {
fn eq(&self, other: &Self) -> bool {
return self.name == other.name;
}
}

impl Eq for BlockDevName {}

/// @brief 块设备应该实现的操作
pub trait BlockDevice: Device {
/// # dev_name
/// 返回块设备的名字
fn dev_name(&self) -> &BlockDevName;

fn blkdev_meta(&self) -> &BlockDevMeta;

/// 获取设备的扇区范围
fn disk_range(&self) -> GeneralBlockRange;

/// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
///
/// @parameter lba_id_start: 起始块
Expand Down Expand Up @@ -379,6 +486,11 @@ pub trait BlockDevice: Device {
}
return Ok(len);
}

/// # gendisk注册成功的回调函数
fn callback_gendisk_registered(&self, _gendisk: &Arc<GenDisk>) -> Result<(), SystemError> {
Ok(())
}
}

/// @brief 块设备框架函数集
Expand Down
46 changes: 34 additions & 12 deletions kernel/src/driver/base/block/disk_info.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
#![allow(dead_code)]
use alloc::sync::{Arc, Weak};
use system_error::SystemError;

use super::block_device::BlockDevice;
use super::block_device::{BlockDevice, GeneralBlockRange};

pub type SectorT = u64;

pub const BLK_TYPE_AHCI: u64 = 0;
pub const DISK_NAME_LEN: usize = 32; // 磁盘名称的最大长度
pub const BLK_GF_AHCI: u16 = 1 << 0; // 定义blk_gendisk中的标志位

/// @brief: 磁盘的分区信息 - (保留了c版本的数据信息)
#[derive(Debug)]
pub struct Partition {
pub start_sector: SectorT, // 该分区的起始扇区
pub lba_start: u64, // 起始LBA号
pub sectors_num: u64, // 该分区的扇区数
disk: Weak<dyn BlockDevice>, // 当前分区所属的磁盘
pub partno: u16, // 在磁盘上的分区号
pub start_sector: SectorT, // 该分区的起始扇区
pub lba_start: u64, // 起始LBA号
pub sectors_num: u64, // 该分区的扇区数
disk: Option<Weak<dyn BlockDevice>>, // 当前分区所属的磁盘
pub partno: u16, // 在磁盘上的分区号
}

/// @brief: 分区信息 - 成员函数
Expand All @@ -33,14 +30,39 @@ impl Partition {
start_sector,
lba_start,
sectors_num,
disk,
disk: Some(disk),
partno,
});
}

pub fn new_raw(start_sector: SectorT, lba_start: u64, sectors_num: u64, partno: u16) -> Self {
return Partition {
start_sector,
lba_start,
sectors_num,
disk: None,
partno,
};
}

/// @brief 获取当前分区所属的磁盘的Arc指针
#[inline]
pub fn disk(&self) -> Arc<dyn BlockDevice> {
return self.disk.upgrade().unwrap();
return self.disk.as_ref().unwrap().upgrade().unwrap();
}
}

impl TryInto<GeneralBlockRange> for Partition {
type Error = SystemError;

fn try_into(self) -> Result<GeneralBlockRange, Self::Error> {
if let Some(range) = GeneralBlockRange::new(
self.lba_start as usize,
(self.lba_start + self.sectors_num) as usize,
) {
return Ok(range);
} else {
return Err(SystemError::EINVAL);
}
}
}
Loading

0 comments on commit 9fa0e95

Please sign in to comment.