xref: /DragonOS/kernel/src/driver/base/block/block_device.rs (revision b8ed38251dc255b0c525801b5dbf37d3b0d0d61e)
1 /// 引入Module
2 use crate::{
3     driver::base::{
4         device::{
5             device_number::{DeviceNumber, Major},
6             Device, DeviceError, IdTable, BLOCKDEVS,
7         },
8         map::{
9             DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
10             DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
11         },
12     },
13     kerror,
14 };
15 
16 use alloc::{sync::Arc, vec::Vec};
17 use core::any::Any;
18 use system_error::SystemError;
19 
20 use super::disk_info::Partition;
21 
22 /// 该文件定义了 Device 和 BlockDevice 的接口
23 /// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示,而不是自己定义错误enum
24 
25 // 使用方法:
26 // 假设 blk_dev 是块设备
27 // <blk_dev as Device>::read_at() 调用的是Device的函数
28 // <blk_dev as BlockDevice>::read_at() 调用的是BlockDevice的函数
29 
30 /// 定义类型
31 pub type BlockId = usize;
32 
33 /// 定义常量
34 pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12.
35 /// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA)
36 pub const LBA_SIZE: usize = 512;
37 
38 /// @brief 块设备的迭代器
39 /// @usage 某次操作读/写块设备的[L,R]范围内的字节,
40 ///        那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange
41 pub struct BlockIter {
42     pub begin: usize, // 迭代器的起始位置 -> 块设备的地址 (单位是字节)
43     pub end: usize,
44     pub blk_size_log2: u8,
45     pub multiblock: bool, // 是否启用连续整块同时遍历
46 }
47 
48 /// @brief Range搭配迭代器BlockIter使用,[L,R]区间被分割成多个小的Range
49 ///        Range要么是整块,要么是一块的某一部分
50 /// 细节: range = [begin, end) 左闭右开
51 pub struct BlockRange {
52     pub lba_start: usize, // 起始块的lba_id
53     pub lba_end: usize,   // 终止块的lba_id
54     pub begin: usize, // 起始位置在块内的偏移量, 如果BlockIter启用Multiblock,则是多个块的偏移量
55     pub end: usize,   // 结束位置在块内的偏移量,单位是字节
56     pub blk_size_log2: u8,
57 }
58 
59 impl BlockIter {
60     #[allow(dead_code)]
61     pub fn new(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
62         return BlockIter {
63             begin: start_addr,
64             end: end_addr,
65             blk_size_log2,
66             multiblock: false,
67         };
68     }
69     pub fn new_multiblock(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
70         return BlockIter {
71             begin: start_addr,
72             end: end_addr,
73 
74             blk_size_log2,
75             multiblock: true,
76         };
77     }
78 
79     /// 获取下一个整块或者不完整的块
80     pub fn next_block(&mut self) -> BlockRange {
81         let blk_size_log2 = self.blk_size_log2;
82         let blk_size = 1usize << self.blk_size_log2;
83         let lba_id = self.begin / blk_size;
84         let begin = self.begin % blk_size;
85         let end = if lba_id == self.end / blk_size {
86             self.end % blk_size
87         } else {
88             blk_size
89         };
90 
91         self.begin += end - begin;
92 
93         return BlockRange {
94             lba_start: lba_id,
95             lba_end: lba_id + 1,
96             begin,
97             end,
98             blk_size_log2,
99         };
100     }
101 
102     /// 如果能返回多个连续的整块,则返回;否则调用next_block()返回不完整的块
103     pub fn next_multiblock(&mut self) -> BlockRange {
104         let blk_size_log2 = self.blk_size_log2;
105         let blk_size = 1usize << self.blk_size_log2;
106         let lba_start = self.begin / blk_size;
107         let lba_end = self.end / blk_size;
108 
109         // 如果不是整块,先返回非整块的小部分
110         if __bytes_to_lba(self.begin, blk_size)
111             != __bytes_to_lba(self.begin + blk_size - 1, blk_size)
112             || lba_start == lba_end
113         {
114             return self.next_block();
115         }
116 
117         let begin = self.begin % blk_size; // 因为是多个整块,这里必然是0
118         let end = __lba_to_bytes(lba_end, blk_size) - self.begin;
119 
120         self.begin += end - begin;
121 
122         return BlockRange {
123             lba_start,
124             lba_end,
125             begin,
126             end,
127             blk_size_log2,
128         };
129     }
130 }
131 
132 /// BlockIter 函数实现
133 impl Iterator for BlockIter {
134     type Item = BlockRange;
135 
136     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
137         if self.begin >= self.end {
138             return None;
139         }
140         if self.multiblock {
141             return Some(self.next_multiblock());
142         } else {
143             return Some(self.next_block());
144         }
145     }
146 }
147 
148 /// BlockRange 函数实现
149 impl BlockRange {
150     #[allow(dead_code)]
151     pub fn is_empty(&self) -> bool {
152         return self.end == self.begin;
153     }
154     pub fn len(&self) -> usize {
155         return self.end - self.begin;
156     }
157     /// 判断是不是整块
158     pub fn is_full(&self) -> bool {
159         return self.len() == (1usize << self.blk_size_log2);
160     }
161     /// 判断是不是多个整块连在一起
162     pub fn is_multi(&self) -> bool {
163         return self.len() >= (1usize << self.blk_size_log2)
164             && (self.len() % (1usize << self.blk_size_log2) == 0);
165     }
166     /// 获取 BlockRange 在块设备内部的起始位置 (单位是字节)
167     pub fn origin_begin(&self) -> usize {
168         return (self.lba_start << self.blk_size_log2) + self.begin;
169     }
170     /// 获取 BlockRange 在块设备内部的结尾位置 (单位是字节)
171     pub fn origin_end(&self) -> usize {
172         return (self.lba_start << self.blk_size_log2) + self.end;
173     }
174 }
175 
176 /// 从字节地址转换到lba id
177 #[inline]
178 pub fn __bytes_to_lba(addr: usize, blk_size: usize) -> BlockId {
179     return addr / blk_size;
180 }
181 
182 /// 从lba id转换到字节地址, 返回lba_id的最左侧字节
183 #[inline]
184 pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
185     return lba_id * blk_size;
186 }
187 
188 /// @brief 块设备应该实现的操作
189 pub trait BlockDevice: Device {
190     /// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
191     ///
192     /// @parameter lba_id_start: 起始块
193     /// @parameter count: 读取块的数量
194     /// @parameter buf: 目标数组
195     /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
196     ///          否则返回Err(错误码),其中错误码为负数;
197     ///          如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
198     fn read_at(
199         &self,
200         lba_id_start: BlockId,
201         count: usize,
202         buf: &mut [u8],
203     ) -> Result<usize, SystemError>;
204 
205     /// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中
206     /// @parameter lba_id_start: 起始块
207     /// @parameter count: 写入块的数量
208     /// @parameter buf: 目标数组
209     /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
210     ///          否则返回Err(错误码),其中错误码为负数;
211     ///          如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
212     fn write_at(
213         &self,
214         lba_id_start: BlockId,
215         count: usize,
216         buf: &[u8],
217     ) -> Result<usize, SystemError>;
218 
219     /// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现
220     fn sync(&self) -> Result<(), SystemError>;
221 
222     /// @brief: 每个块设备都必须固定自己块大小,而且该块大小必须是2的幂次
223     /// @return: 返回一个固定量,硬编码(编程的时候固定的常量).
224     fn blk_size_log2(&self) -> u8;
225 
226     // TODO: 待实现 open, close
227 
228     /// @brief 本函数用于实现动态转换。
229     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
230     fn as_any_ref(&self) -> &dyn Any;
231 
232     /// @brief 本函数用于将BlockDevice转换为Device。
233     /// 由于实现了BlockDevice的结构体,本身也实现了Device Trait, 因此转换是可能的。
234     /// 思路:在BlockDevice的结构体中新增一个self_ref变量,返回self_ref.upgrade()即可。
235     fn device(&self) -> Arc<dyn Device>;
236 
237     /// @brief 返回块设备的块大小(单位:字节)
238     fn block_size(&self) -> usize;
239 
240     /// @brief 返回当前磁盘上的所有分区的Arc指针数组
241     fn partitions(&self) -> Vec<Arc<Partition>>;
242 
243     fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
244         // assert!(len <= buf.len());
245         if len > buf.len() {
246             return Err(SystemError::E2BIG);
247         }
248 
249         let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
250         let multi = iter.multiblock;
251 
252         for range in iter {
253             let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
254             let buf_end = range.origin_end() - offset;
255             let buf_slice = &buf[buf_begin..buf_end];
256             let count: usize = range.lba_end - range.lba_start;
257             let full = multi && range.is_multi() || !multi && range.is_full();
258 
259             if full {
260                 self.write_at(range.lba_start, count, buf_slice)?;
261             } else {
262                 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
263                     return Err(SystemError::E2BIG);
264                 }
265 
266                 let mut temp = vec![0; 1usize << self.blk_size_log2()];
267                 // 由于块设备每次读写都是整块的,在不完整写入之前,必须把不完整的地方补全
268                 self.read_at(range.lba_start, 1, &mut temp[..])?;
269                 // 把数据从临时buffer复制到目标buffer
270                 temp[range.begin..range.end].copy_from_slice(buf_slice);
271                 self.write_at(range.lba_start, 1, &temp[..])?;
272             }
273         }
274         return Ok(len);
275         //self.0.lock().write_at(lba_id_start, count, buf)
276     }
277 
278     fn read_at_bytes(
279         &self,
280         offset: usize,
281         len: usize,
282         buf: &mut [u8],
283     ) -> Result<usize, SystemError> {
284         if len > buf.len() {
285             return Err(SystemError::E2BIG);
286         }
287 
288         let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
289         let multi = iter.multiblock;
290 
291         // 枚举每一个range
292         for range in iter {
293             let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
294             let buf_end = range.origin_end() - offset;
295             let buf_slice = &mut buf[buf_begin..buf_end];
296             let count: usize = range.lba_end - range.lba_start;
297             let full = multi && range.is_multi() || !multi && range.is_full();
298 
299             // 读取整个block作为有效数据
300             if full {
301                 // 调用 BlockDevice::read_at() 直接把引用传进去,不是把整个数组move进去
302                 self.read_at(range.lba_start, count, buf_slice)?;
303             } else {
304                 // 判断块的长度不能超过最大值
305                 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
306                     return Err(SystemError::E2BIG);
307                 }
308 
309                 let mut temp = vec![0; 1usize << self.blk_size_log2()];
310                 self.read_at(range.lba_start, 1, &mut temp[..])?;
311 
312                 // 把数据从临时buffer复制到目标buffer
313                 buf_slice.copy_from_slice(&temp[range.begin..range.end]);
314             }
315         }
316         return Ok(len);
317 
318         // kdebug!(
319         //     "ahci read at {lba_id_start}, count={count}, lock={:?}",
320         //     self.0
321         // );
322     }
323 }
324 
325 /// @brief 块设备框架函数集
326 pub struct BlockDeviceOps;
327 
328 impl BlockDeviceOps {
329     /// @brief: 主设备号转下标
330     /// @parameter: major: 主设备号
331     /// @return: 返回下标
332     #[allow(dead_code)]
333     fn major_to_index(major: Major) -> usize {
334         return (major.data() % DEV_MAJOR_HASH_SIZE) as usize;
335     }
336 
337     /// @brief: 动态获取主设备号
338     /// @parameter: None
339     /// @return: 如果成功,返回主设备号,否则,返回错误码
340     #[allow(dead_code)]
341     fn find_dynamic_major() -> Result<Major, SystemError> {
342         let blockdevs = BLOCKDEVS.lock();
343         // 寻找主设备号为234~255的设备
344         for index in ((DEV_MAJOR_DYN_END.data())..DEV_MAJOR_HASH_SIZE).rev() {
345             if let Some(item) = blockdevs.get(index as usize) {
346                 if item.is_empty() {
347                     return Ok(Major::new(index)); // 返回可用的主设备号
348                 }
349             }
350         }
351         // 寻找主设备号在384~511的设备
352         for index in
353             ((DEV_MAJOR_DYN_EXT_END.data() + 1)..(DEV_MAJOR_DYN_EXT_START.data() + 1)).rev()
354         {
355             if let Some(blockdevss) = blockdevs.get(Self::major_to_index(Major::new(index))) {
356                 let mut flag = true;
357                 for item in blockdevss {
358                     if item.device_number().major() == Major::new(index) {
359                         flag = false;
360                         break;
361                     }
362                 }
363                 if flag {
364                     // 如果数组中不存在主设备号等于index的设备
365                     return Ok(Major::new(index)); // 返回可用的主设备号
366                 }
367             }
368         }
369         return Err(SystemError::EBUSY);
370     }
371 
372     /// @brief: 注册设备号,该函数需要指定主设备号
373     /// @parameter: from: 主设备号
374     ///             count: 次设备号数量
375     ///             name: 字符设备名
376     /// @return: 如果注册成功,返回设备号,否则,返回错误码
377     #[allow(dead_code)]
378     pub fn register_blockdev_region(
379         from: DeviceNumber,
380         count: u32,
381         name: &'static str,
382     ) -> Result<DeviceNumber, SystemError> {
383         Self::__register_blockdev_region(from, count, name)
384     }
385 
386     /// @brief: 注册设备号,该函数自动分配主设备号
387     /// @parameter: baseminor: 主设备号
388     ///             count: 次设备号数量
389     ///             name: 字符设备名
390     /// @return: 如果注册成功,返回,否则,返回false
391     #[allow(dead_code)]
392     pub fn alloc_blockdev_region(
393         baseminor: u32,
394         count: u32,
395         name: &'static str,
396     ) -> Result<DeviceNumber, SystemError> {
397         Self::__register_blockdev_region(
398             DeviceNumber::new(Major::UNNAMED_MAJOR, baseminor),
399             count,
400             name,
401         )
402     }
403 
404     /// @brief: 注册设备号
405     /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
406     ///             minorct: 次设备号数量
407     ///             name: 字符设备名
408     /// @return: 如果注册成功,返回设备号,否则,返回错误码
409     fn __register_blockdev_region(
410         device_number: DeviceNumber,
411         minorct: u32,
412         name: &'static str,
413     ) -> Result<DeviceNumber, SystemError> {
414         let mut major = device_number.major();
415         let baseminor = device_number.minor();
416         if major >= DEV_MAJOR_MAX {
417             kerror!(
418                 "DEV {} major requested {:?} is greater than the maximum {}\n",
419                 name,
420                 major,
421                 DEV_MAJOR_MAX.data() - 1
422             );
423         }
424         if minorct > DeviceNumber::MINOR_MASK + 1 - baseminor {
425             kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
426                 name, baseminor, baseminor + minorct - 1, 0, DeviceNumber::MINOR_MASK);
427         }
428         let blockdev = DeviceStruct::new(DeviceNumber::new(major, baseminor), minorct, name);
429         if major == Major::UNNAMED_MAJOR {
430             // 如果主设备号为0,则自动分配主设备号
431             major = Self::find_dynamic_major().expect("Find synamic major error.\n");
432         }
433         if let Some(items) = BLOCKDEVS.lock().get_mut(Self::major_to_index(major)) {
434             let mut insert_index: usize = 0;
435             for (index, item) in items.iter().enumerate() {
436                 insert_index = index;
437                 match item.device_number().major().cmp(&major) {
438                     core::cmp::Ordering::Less => continue,
439                     core::cmp::Ordering::Greater => {
440                         break; // 大于则向后插入
441                     }
442                     core::cmp::Ordering::Equal => {
443                         if item.device_number().minor() + item.minorct() <= baseminor {
444                             continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
445                         }
446                         if item.base_minor() >= baseminor + minorct {
447                             break; // 在此处插入
448                         }
449                         return Err(SystemError::EBUSY); // 存在重合的次设备号
450                     }
451                 }
452             }
453             items.insert(insert_index, blockdev);
454         }
455 
456         return Ok(DeviceNumber::new(major, baseminor));
457     }
458 
459     /// @brief: 注销设备号
460     /// @parameter: major: 主设备号,如果为0,动态分配
461     ///             baseminor: 起始次设备号
462     ///             minorct: 次设备号数量
463     /// @return: 如果注销成功,返回(),否则,返回错误码
464     fn __unregister_blockdev_region(
465         device_number: DeviceNumber,
466         minorct: u32,
467     ) -> Result<(), SystemError> {
468         if let Some(items) = BLOCKDEVS
469             .lock()
470             .get_mut(Self::major_to_index(device_number.major()))
471         {
472             for (index, item) in items.iter().enumerate() {
473                 if item.device_number() == device_number && item.minorct() == minorct {
474                     // 设备号和数量都相等
475                     items.remove(index);
476                     return Ok(());
477                 }
478             }
479         }
480         return Err(SystemError::EBUSY);
481     }
482 
483     /// @brief: 块设备注册
484     /// @parameter: cdev: 字符设备实例
485     ///             dev_t: 字符设备号
486     ///             range: 次设备号范围
487     /// @return: none
488     #[allow(dead_code)]
489     pub fn bdev_add(_bdev: Arc<dyn BlockDevice>, id_table: IdTable) -> Result<(), DeviceError> {
490         if id_table.device_number().data() == 0 {
491             kerror!("Device number can't be 0!\n");
492         }
493         todo!("bdev_add")
494         // return device_manager().add_device(bdev.id_table(), bdev.device());
495     }
496 
497     /// @brief: block设备注销
498     /// @parameter: dev_t: 字符设备号
499     ///             range: 次设备号范围
500     /// @return: none
501     #[allow(dead_code)]
502     pub fn bdev_del(_devnum: DeviceNumber, _range: usize) {
503         unimplemented!();
504     }
505 }
506