123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- use core::{
- ops::{Deref, DerefMut},
- sync::atomic::{AtomicU32, Ordering},
- };
- use alloc::{
- string::String,
- sync::{Arc, Weak},
- };
- use hashbrown::HashMap;
- use system_error::SystemError;
- use crate::{
- driver::base::device::device_number::DeviceNumber,
- filesystem::{
- devfs::{DevFS, DeviceINode, LockedDevFSInode},
- vfs::{syscall::ModeType, utils::DName, IndexNode, Metadata},
- },
- libs::{rwlock::RwLock, spinlock::SpinLockGuard},
- };
- use super::block_device::{BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE};
- const MINORS_PER_DISK: u32 = 256;
- #[derive(Debug)]
- pub struct GenDisk {
- bdev: Weak<dyn BlockDevice>,
- range: GeneralBlockRange,
- block_size_log2: u8,
- idx: Option<u32>,
- device_num: DeviceNumber,
- parent: RwLock<Weak<LockedDevFSInode>>,
- fs: RwLock<Weak<DevFS>>,
- metadata: Metadata,
- /// 对应/dev/下的设备名
- name: DName,
- }
- impl GenDisk {
- /// 如果gendisk是整个磁盘,则idx为u32::MAX
- pub const ENTIRE_DISK_IDX: u32 = u32::MAX;
- pub fn new(
- bdev: Weak<dyn BlockDevice>,
- range: GeneralBlockRange,
- idx: Option<u32>,
- dev_name: DName,
- ) -> Arc<Self> {
- let bsizelog2 = bdev.upgrade().unwrap().blk_size_log2();
- // 对应整块硬盘的情况
- let id = idx.unwrap_or(0);
- if id >= MINORS_PER_DISK {
- panic!("GenDisk index out of range: {}", id);
- }
- let ptr = bdev.upgrade().unwrap();
- let meta = ptr.blkdev_meta();
- let major = meta.major;
- let minor = meta.base_minor * MINORS_PER_DISK + id;
- // log::info!("New gendisk: major: {}, minor: {}", major, minor);
- let device_num = DeviceNumber::new(major, minor);
- return Arc::new(GenDisk {
- bdev,
- range,
- block_size_log2: bsizelog2,
- idx,
- device_num,
- parent: RwLock::new(Weak::default()),
- fs: RwLock::new(Weak::default()),
- metadata: Metadata::new(
- crate::filesystem::vfs::FileType::BlockDevice,
- ModeType::from_bits_truncate(0o755),
- ),
- name: dev_name,
- });
- }
- pub fn block_device(&self) -> Arc<dyn BlockDevice> {
- return self.bdev.upgrade().unwrap();
- }
- /// # read_at
- ///
- /// 读取分区内的数据
- ///
- /// ## 参数
- ///
- /// - buf: 输出缓冲区,大小必须为LBA_SIZE的整数倍,否则返回EINVAL
- /// - start_block_offset: 分区内的块号
- pub fn read_at(
- &self,
- buf: &mut [u8],
- start_block_offset: BlockId,
- ) -> Result<usize, SystemError> {
- if (buf.len() & (LBA_SIZE - 1)) > 0 {
- return Err(SystemError::EINVAL);
- }
- let blocks = buf.len() / (1 << self.block_size_log2 as usize);
- let lba = self.block_offset_2_disk_blkid(start_block_offset);
- return self.block_device().read_at(lba, blocks, buf);
- }
- /// # read_at_bytes
- ///
- /// 按字节偏移量从分区中读取数据
- ///
- /// ## 参数
- ///
- /// - buf: 输出缓冲区
- /// - bytes_offset: 分区内的字节偏移量
- pub fn read_at_bytes(&self, buf: &mut [u8], bytes_offset: usize) -> Result<usize, SystemError> {
- let start_lba = self.range.lba_start;
- let bytes_offset = self.disk_blkid_2_bytes(start_lba) + bytes_offset;
- return self
- .block_device()
- .read_at_bytes(bytes_offset, buf.len(), buf);
- }
- /// # 分区内的字节偏移量转换为磁盘上的字节偏移量
- pub fn disk_bytes_offset(&self, bytes_offset: usize) -> usize {
- let start_lba = self.range.lba_start;
- return self.disk_blkid_2_bytes(start_lba) + bytes_offset;
- }
- /// # write_at_bytes
- ///
- /// 按字节偏移量向分区写入数据
- ///
- /// ## 参数
- ///
- /// - buf: 输入缓冲区
- /// - bytes_offset: 分区内的字节偏移量
- pub fn write_at_bytes(&self, buf: &[u8], bytes_offset: usize) -> Result<usize, SystemError> {
- let start_lba = self.range.lba_start;
- let bytes_offset = self.disk_blkid_2_bytes(start_lba) + bytes_offset;
- return self
- .block_device()
- .write_at_bytes(bytes_offset, buf.len(), buf);
- }
- /// # write_at
- ///
- /// 向分区内写入数据
- ///
- /// ## 参数
- ///
- /// - buf: 输入缓冲区,大小必须为LBA_SIZE的整数倍,否则返回EINVAL
- /// - start_block_offset: 分区内的块号
- pub fn write_at(&self, buf: &[u8], start_block_offset: BlockId) -> Result<usize, SystemError> {
- if (buf.len() & (LBA_SIZE - 1)) > 0 {
- return Err(SystemError::EINVAL);
- }
- let blocks = buf.len() / (1 << self.block_size_log2 as usize);
- let lba = self.block_offset_2_disk_blkid(start_block_offset);
- return self.block_device().write_at(lba, blocks, buf);
- }
- #[inline]
- pub fn block_offset_2_disk_blkid(&self, block_offset: BlockId) -> BlockId {
- self.range.lba_start + block_offset
- }
- #[inline]
- fn disk_blkid_2_bytes(&self, disk_blkid: BlockId) -> usize {
- disk_blkid * LBA_SIZE
- }
- #[inline]
- pub fn idx(&self) -> u32 {
- self.idx.unwrap_or(Self::ENTIRE_DISK_IDX)
- }
- #[inline]
- pub fn range(&self) -> &GeneralBlockRange {
- &self.range
- }
- #[inline]
- pub fn device_num(&self) -> DeviceNumber {
- self.device_num
- }
- #[inline]
- pub fn minor(&self) -> u32 {
- self.device_num.minor()
- }
- /// # sync
- /// 同步磁盘
- pub fn sync(&self) -> Result<(), SystemError> {
- self.block_device().sync()
- }
- pub fn symlink_name(&self) -> String {
- let major = self.device_num.major().data();
- let minor = self.device_num.minor();
- format!("{}:{}", major, minor)
- }
- pub fn block_size_log2(&self) -> u8 {
- self.block_size_log2
- }
- }
- impl IndexNode for GenDisk {
- fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
- self.fs.read().upgrade().unwrap()
- }
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn read_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &mut [u8],
- _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- Err(SystemError::EPERM)
- }
- fn write_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &[u8],
- _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<usize, SystemError> {
- Err(SystemError::EPERM)
- }
- fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
- Err(SystemError::ENOSYS)
- }
- fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
- Ok(self.metadata.clone())
- }
- fn dname(&self) -> Result<DName, SystemError> {
- Ok(self.name.clone())
- }
- fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
- let parent = self.parent.read();
- if let Some(parent) = parent.upgrade() {
- return Ok(parent as Arc<dyn IndexNode>);
- }
- Err(SystemError::ENOENT)
- }
- fn close(
- &self,
- _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- fn open(
- &self,
- _data: SpinLockGuard<crate::filesystem::vfs::FilePrivateData>,
- _mode: &crate::filesystem::vfs::file::FileMode,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- }
- impl DeviceINode for GenDisk {
- fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
- *self.fs.write() = fs;
- }
- fn set_parent(&self, parent: Weak<LockedDevFSInode>) {
- *self.parent.write() = parent;
- }
- }
- #[derive(Default)]
- pub struct GenDiskMap {
- data: HashMap<u32, Arc<GenDisk>>,
- max_idx: AtomicU32,
- }
- impl GenDiskMap {
- pub fn new() -> Self {
- GenDiskMap {
- data: HashMap::new(),
- max_idx: AtomicU32::new(1),
- }
- }
- #[inline]
- #[allow(dead_code)]
- pub fn max_idx(&self) -> u32 {
- self.max_idx.load(Ordering::SeqCst)
- }
- #[inline]
- pub fn alloc_idx(&self) -> u32 {
- self.max_idx.fetch_add(1, Ordering::SeqCst)
- }
- pub fn intersects(&self, range: &GeneralBlockRange) -> bool {
- for (_, v) in self.iter() {
- if range.intersects_with(&v.range).is_some() {
- return true;
- }
- }
- return false;
- }
- }
- impl Deref for GenDiskMap {
- type Target = HashMap<u32, Arc<GenDisk>>;
- fn deref(&self) -> &Self::Target {
- &self.data
- }
- }
- impl DerefMut for GenDiskMap {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.data
- }
- }
|