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