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