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