xref: /DragonOS/kernel/src/driver/base/block/manager.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1 use core::fmt::Formatter;
2 
3 use alloc::sync::Arc;
4 use hashbrown::HashMap;
5 use system_error::SystemError;
6 use unified_init::macros::unified_init;
7 
8 use crate::{
9     driver::base::block::gendisk::GenDisk,
10     filesystem::mbr::MbrDiskPartionTable,
11     init::initcall::INITCALL_POSTCORE,
12     libs::spinlock::{SpinLock, SpinLockGuard},
13 };
14 
15 use super::{
16     block_device::{BlockDevName, BlockDevice, GeneralBlockRange},
17     gendisk::GenDiskMap,
18 };
19 
20 static mut BLOCK_DEV_MANAGER: Option<BlockDevManager> = None;
21 
22 #[inline]
block_dev_manager() -> &'static BlockDevManager23 pub fn block_dev_manager() -> &'static BlockDevManager {
24     unsafe { BLOCK_DEV_MANAGER.as_ref().unwrap() }
25 }
26 
27 #[unified_init(INITCALL_POSTCORE)]
block_dev_manager_init() -> Result<(), SystemError>28 pub fn block_dev_manager_init() -> Result<(), SystemError> {
29     unsafe {
30         BLOCK_DEV_MANAGER = Some(BlockDevManager::new());
31     }
32     Ok(())
33 }
34 
35 /// 磁盘设备管理器
36 pub struct BlockDevManager {
37     inner: SpinLock<InnerBlockDevManager>,
38 }
39 
40 struct InnerBlockDevManager {
41     disks: HashMap<BlockDevName, Arc<dyn BlockDevice>>,
42 }
43 impl BlockDevManager {
new() -> Self44     pub fn new() -> Self {
45         BlockDevManager {
46             inner: SpinLock::new(InnerBlockDevManager {
47                 disks: HashMap::new(),
48             }),
49         }
50     }
51 
inner(&self) -> SpinLockGuard<InnerBlockDevManager>52     fn inner(&self) -> SpinLockGuard<InnerBlockDevManager> {
53         self.inner.lock()
54     }
55 
56     /// 注册磁盘设备
register(&self, dev: Arc<dyn BlockDevice>) -> Result<(), SystemError>57     pub fn register(&self, dev: Arc<dyn BlockDevice>) -> Result<(), SystemError> {
58         let mut inner = self.inner();
59         let dev_name = dev.dev_name();
60         if inner.disks.contains_key(dev_name) {
61             return Err(SystemError::EEXIST);
62         }
63         inner.disks.insert(dev_name.clone(), dev.clone());
64 
65         let mut out_remove = || {
66             inner.disks.remove(dev_name);
67         };
68 
69         // 检测分区表,并创建gendisk
70         self.check_partitions(&dev).inspect_err(|_| out_remove())?;
71         Ok(())
72     }
73 
74     /// 检测分区表,并创建gendisk
check_partitions(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError>75     fn check_partitions(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError> {
76         if self.check_mbr(dev).is_ok() {
77             return Ok(());
78         }
79 
80         // use entire disk as a gendisk
81         self.register_entire_disk_as_gendisk(dev)
82     }
83 
check_mbr(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError>84     fn check_mbr(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError> {
85         let mbr = MbrDiskPartionTable::from_disk(dev.clone())?;
86         let piter = mbr.partitions_raw();
87         for p in piter {
88             self.register_gendisk_with_range(dev, p.try_into()?)?;
89         }
90         Ok(())
91     }
92 
93     /// 将整个磁盘注册为gendisk
register_entire_disk_as_gendisk( &self, dev: &Arc<dyn BlockDevice>, ) -> Result<(), SystemError>94     fn register_entire_disk_as_gendisk(
95         &self,
96         dev: &Arc<dyn BlockDevice>,
97     ) -> Result<(), SystemError> {
98         let range = dev.disk_range();
99         self.register_gendisk_with_range(dev, range)
100     }
101 
register_gendisk_with_range( &self, dev: &Arc<dyn BlockDevice>, range: GeneralBlockRange, ) -> Result<(), SystemError>102     fn register_gendisk_with_range(
103         &self,
104         dev: &Arc<dyn BlockDevice>,
105         range: GeneralBlockRange,
106     ) -> Result<(), SystemError> {
107         let weak_dev = Arc::downgrade(dev);
108         let gendisk = GenDisk::new(
109             weak_dev,
110             range,
111             Some(dev.blkdev_meta().inner().gendisks.alloc_idx()),
112         );
113         self.register_gendisk(dev, gendisk)
114     }
115 
register_gendisk( &self, dev: &Arc<dyn BlockDevice>, gendisk: Arc<GenDisk>, ) -> Result<(), SystemError>116     fn register_gendisk(
117         &self,
118         dev: &Arc<dyn BlockDevice>,
119         gendisk: Arc<GenDisk>,
120     ) -> Result<(), SystemError> {
121         let blk_meta = dev.blkdev_meta();
122         let idx = gendisk.idx();
123         let mut meta_inner = blk_meta.inner();
124         // 检查是否重复
125         if meta_inner.gendisks.intersects(gendisk.range()) {
126             return Err(SystemError::EEXIST);
127         }
128 
129         meta_inner.gendisks.insert(idx, gendisk.clone());
130         dev.callback_gendisk_registered(&gendisk).inspect_err(|_| {
131             meta_inner.gendisks.remove(&idx);
132         })?;
133         Ok(())
134     }
135 
136     /// 卸载磁盘设备
137     #[allow(dead_code)]
unregister(&self, dev: &Arc<dyn BlockDevice>)138     pub fn unregister(&self, dev: &Arc<dyn BlockDevice>) {
139         let mut inner = self.inner();
140         inner.disks.remove(dev.dev_name());
141         // todo: 这里应该callback一下磁盘设备,但是现在还没实现热插拔,所以暂时没做这里
142         todo!("BlockDevManager: unregister disk")
143     }
144 
145     /// 通过路径查找gendisk
146     ///
147     /// # 参数
148     ///
149     /// - `path`: 分区路径 `/dev/sda1` 或者 `sda1`,或者是`/dev/sda`
lookup_gendisk_by_path(&self, path: &str) -> Option<Arc<GenDisk>>150     pub fn lookup_gendisk_by_path(&self, path: &str) -> Option<Arc<GenDisk>> {
151         let (devname, partno) = self.path2devname(path)?;
152         let inner = self.inner();
153         for dev in inner.disks.values() {
154             if dev.dev_name().as_str() == devname {
155                 return dev.blkdev_meta().inner().gendisks.get(&partno).cloned();
156             }
157         }
158         None
159     }
160 
161     /// 打印所有的gendisk的路径
print_gendisks(&self)162     pub fn print_gendisks(&self) {
163         let mut disks = alloc::vec::Vec::new();
164 
165         let inner = self.inner();
166         for dev in inner.disks.values() {
167             let meta = dev.blkdev_meta().inner();
168             for idx in meta.gendisks.keys() {
169                 if idx == &GenDisk::ENTIRE_DISK_IDX {
170                     disks.push(format!("/dev/{}", dev.dev_name()));
171                 } else {
172                     disks.push(format!("/dev/{}{}", dev.dev_name(), idx));
173                 }
174             }
175         }
176 
177         log::debug!("All gendisks: {:?}", disks);
178     }
179 
180     /// 将路径转换为设备名以及分区号
181     ///
182     /// 例如: sda1 -> (sda, 1)  nvme0n1p1 -> (nvme0n1, 1)
path2devname<'a>(&self, mut path: &'a str) -> Option<(&'a str, u32)>183     fn path2devname<'a>(&self, mut path: &'a str) -> Option<(&'a str, u32)> {
184         // 去除开头的"/dev/"
185         if path.starts_with("/dev/") {
186             path = path.strip_prefix("/dev/")?;
187         }
188 
189         let mut partno = GenDisk::ENTIRE_DISK_IDX;
190         // 截取末尾数字
191         let mut last_digit = path.len();
192         while last_digit > 0 && path.chars().nth(last_digit - 1).unwrap().is_ascii_digit() {
193             last_digit -= 1;
194         }
195         if last_digit == 0 {
196             return (path, GenDisk::ENTIRE_DISK_IDX).into();
197         }
198 
199         if last_digit < path.len() {
200             partno = path[last_digit..].parse().ok()?;
201         }
202 
203         let path = &path[..last_digit];
204 
205         Some((path, partno))
206     }
207 }
208 
209 pub struct BlockDevMeta {
210     pub devname: BlockDevName,
211     inner: SpinLock<InnerBlockDevMeta>,
212 }
213 
214 pub struct InnerBlockDevMeta {
215     pub gendisks: GenDiskMap,
216 }
217 
218 impl BlockDevMeta {
new(devname: BlockDevName) -> Self219     pub fn new(devname: BlockDevName) -> Self {
220         BlockDevMeta {
221             devname,
222             inner: SpinLock::new(InnerBlockDevMeta {
223                 gendisks: GenDiskMap::new(),
224             }),
225         }
226     }
227 
inner(&self) -> SpinLockGuard<InnerBlockDevMeta>228     fn inner(&self) -> SpinLockGuard<InnerBlockDevMeta> {
229         self.inner.lock()
230     }
231 }
232 
233 impl core::fmt::Debug for BlockDevMeta {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result234     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
235         f.debug_struct("BlockDevMeta")
236             .field("devname", &self.devname)
237             .finish()
238     }
239 }
240