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