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