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 /// 卸载磁盘设备
unregister(&self, dev: &Arc<dyn BlockDevice>)137 pub fn unregister(&self, dev: &Arc<dyn BlockDevice>) {
138 let mut inner = self.inner();
139 inner.disks.remove(dev.dev_name());
140 // todo: 这里应该callback一下磁盘设备,但是现在还没实现热插拔,所以暂时没做这里
141 todo!("BlockDevManager: unregister disk")
142 }
143
144 /// 通过路径查找gendisk
145 ///
146 /// # 参数
147 ///
148 /// - `path`: 分区路径 `/dev/sda1` 或者 `sda1`,或者是`/dev/sda`
lookup_gendisk_by_path(&self, path: &str) -> Option<Arc<GenDisk>>149 pub fn lookup_gendisk_by_path(&self, path: &str) -> Option<Arc<GenDisk>> {
150 let (devname, partno) = self.path2devname(path)?;
151 let inner = self.inner();
152 for dev in inner.disks.values() {
153 if dev.dev_name().as_str() == devname {
154 return dev.blkdev_meta().inner().gendisks.get(&partno).cloned();
155 }
156 }
157 None
158 }
159
160 /// 打印所有的gendisk的路径
print_gendisks(&self)161 pub fn print_gendisks(&self) {
162 let mut disks = alloc::vec::Vec::new();
163
164 let inner = self.inner();
165 for dev in inner.disks.values() {
166 let meta = dev.blkdev_meta().inner();
167 for idx in meta.gendisks.keys() {
168 if idx == &GenDisk::ENTIRE_DISK_IDX {
169 disks.push(format!("/dev/{}", dev.dev_name()));
170 } else {
171 disks.push(format!("/dev/{}{}", dev.dev_name(), idx));
172 }
173 }
174 }
175
176 log::debug!("All gendisks: {:?}", disks);
177 }
178
179 /// 将路径转换为设备名以及分区号
180 ///
181 /// 例如: sda1 -> (sda, 1) nvme0n1p1 -> (nvme0n1, 1)
path2devname<'a>(&self, mut path: &'a str) -> Option<(&'a str, u32)>182 fn path2devname<'a>(&self, mut path: &'a str) -> Option<(&'a str, u32)> {
183 // 去除开头的"/dev/"
184 if path.starts_with("/dev/") {
185 path = path.strip_prefix("/dev/")?;
186 }
187
188 let mut partno = GenDisk::ENTIRE_DISK_IDX;
189 // 截取末尾数字
190 let mut last_digit = path.len();
191 while last_digit > 0 && path.chars().nth(last_digit - 1).unwrap().is_ascii_digit() {
192 last_digit -= 1;
193 }
194 if last_digit == 0 {
195 return (path, GenDisk::ENTIRE_DISK_IDX).into();
196 }
197
198 if last_digit < path.len() {
199 partno = path[last_digit..].parse().ok()?;
200 }
201
202 let path = &path[..last_digit];
203
204 Some((path, partno))
205 }
206 }
207
208 pub struct BlockDevMeta {
209 pub devname: BlockDevName,
210 inner: SpinLock<InnerBlockDevMeta>,
211 }
212
213 pub struct InnerBlockDevMeta {
214 pub gendisks: GenDiskMap,
215 }
216
217 impl BlockDevMeta {
new(devname: BlockDevName) -> Self218 pub fn new(devname: BlockDevName) -> Self {
219 BlockDevMeta {
220 devname,
221 inner: SpinLock::new(InnerBlockDevMeta {
222 gendisks: GenDiskMap::new(),
223 }),
224 }
225 }
226
inner(&self) -> SpinLockGuard<InnerBlockDevMeta>227 fn inner(&self) -> SpinLockGuard<InnerBlockDevMeta> {
228 self.inner.lock()
229 }
230 }
231
232 impl core::fmt::Debug for BlockDevMeta {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result233 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
234 f.debug_struct("BlockDevMeta")
235 .field("devname", &self.devname)
236 .finish()
237 }
238 }
239