1 /// 引入Module
2 use crate::syscall::SystemError;
3 use alloc::{sync::Arc, vec::Vec};
4 use core::{any::Any, fmt::Debug};
5 
6 use super::disk_info::Partition;
7 
8 /// 该文件定义了 Device 和 BlockDevice 的接口
9 /// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示,而不是自己定义错误enum
10 
11 // 使用方法:
12 // 假设 blk_dev 是块设备
13 // <blk_dev as Device>::read_at() 调用的是Device的函数
14 // <blk_dev as BlockDevice>::read_at() 调用的是BlockDevice的函数
15 
16 /// 定义类型
17 pub type BlockId = usize;
18 
19 /// 定义常量
20 const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12.
21 /// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA)
22 pub const LBA_SIZE: usize = 512;
23 
24 /// @brief 设备应该实现的操作
25 /// @usage Device::read_at()
26 pub trait Device: Any + Send + Sync + Debug {
27     /// Notice buffer对应设备按字节划分,使用u8类型
28     /// Notice offset应该从0开始计数
29 
30     /// @brief: 从设备的第offset个字节开始,读取len个byte,存放到buf中
31     /// @parameter offset: 起始字节偏移量
32     /// @parameter len: 读取字节的数量
33     /// @parameter buf: 目标数组
34     /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>35     fn read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>;
36 
37     /// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中
38     /// @parameter offset: 起始字节偏移量
39     /// @parameter len: 读取字节的数量
40     /// @parameter buf: 目标数组
41     /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度
write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError>42     fn write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError>;
43 
44     /// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现
sync(&self) -> Result<(), SystemError>45     fn sync(&self) -> Result<(), SystemError>;
46 
47     // TODO: 待实现 open, close
48 }
49 
50 /// @brief 块设备应该实现的操作
51 pub trait BlockDevice: Any + Send + Sync + Debug {
52     /// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
53     ///
54     /// @parameter lba_id_start: 起始块
55     /// @parameter count: 读取块的数量
56     /// @parameter buf: 目标数组
57     /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
58     ///          否则返回Err(错误码),其中错误码为负数;
59     ///          如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
read_at( &self, lba_id_start: BlockId, count: usize, buf: &mut [u8], ) -> Result<usize, SystemError>60     fn read_at(
61         &self,
62         lba_id_start: BlockId,
63         count: usize,
64         buf: &mut [u8],
65     ) -> Result<usize, SystemError>;
66 
67     /// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中
68     /// @parameter lba_id_start: 起始块
69     /// @parameter count: 写入块的数量
70     /// @parameter buf: 目标数组
71     /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
72     ///          否则返回Err(错误码),其中错误码为负数;
73     ///          如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
write_at( &self, lba_id_start: BlockId, count: usize, buf: &[u8], ) -> Result<usize, SystemError>74     fn write_at(
75         &self,
76         lba_id_start: BlockId,
77         count: usize,
78         buf: &[u8],
79     ) -> Result<usize, SystemError>;
80 
81     /// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现
sync(&self) -> Result<(), SystemError>82     fn sync(&self) -> Result<(), SystemError>;
83 
84     /// @brief: 每个块设备都必须固定自己块大小,而且该块大小必须是2的幂次
85     /// @return: 返回一个固定量,硬编码(编程的时候固定的常量).
blk_size_log2(&self) -> u886     fn blk_size_log2(&self) -> u8;
87 
88     // TODO: 待实现 open, close
89 
90     /// @brief 本函数用于实现动态转换。
91     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
as_any_ref(&self) -> &dyn Any92     fn as_any_ref(&self) -> &dyn Any;
93 
94     /// @brief 本函数用于将BlockDevice转换为Device。
95     /// 由于实现了BlockDevice的结构体,本身也实现了Device Trait, 因此转换是可能的。
96     /// 思路:在BlockDevice的结构体中新增一个self_ref变量,返回self_ref.upgrade()即可。
device(&self) -> Arc<dyn Device>97     fn device(&self) -> Arc<dyn Device>;
98 
99     /// @brief 返回块设备的块大小(单位:字节)
block_size(&self) -> usize100     fn block_size(&self) -> usize;
101 
102     /// @brief 返回当前磁盘上的所有分区的Arc指针数组
partitions(&self) -> Vec<Arc<Partition>>103     fn partitions(&self) -> Vec<Arc<Partition>>;
104 }
105 
106 /// 对于所有<块设备>自动实现 Device Trait 的 read_at 和 write_at 函数
107 impl<T: BlockDevice> Device for T {
108     // 读取设备操作,读取设备内部 [offset, offset + buf.len) 区间内的字符,存放到 buf 中
read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>109     fn read_at(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
110         if len > buf.len() {
111             return Err(SystemError::E2BIG);
112         }
113 
114         let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
115         let multi = iter.multiblock;
116 
117         // 枚举每一个range
118         for range in iter {
119             let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
120             let buf_end = range.origin_end() - offset;
121             let buf_slice = &mut buf[buf_begin..buf_end];
122             let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
123             let full = multi && range.is_multi() || !multi && range.is_full();
124 
125             if full {
126                 // 调用 BlockDevice::read_at() 直接把引用传进去,不是把整个数组move进去
127                 BlockDevice::read_at(self, range.lba_start, count, buf_slice)?;
128             } else {
129                 // 判断块的长度不能超过最大值
130                 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
131                     return Err(SystemError::E2BIG);
132                 }
133 
134                 let mut temp = Vec::new();
135                 temp.resize(1usize << self.blk_size_log2(), 0);
136                 BlockDevice::read_at(self, range.lba_start, 1, &mut temp[..])?;
137                 // 把数据从临时buffer复制到目标buffer
138                 buf_slice.copy_from_slice(&temp[range.begin..range.end]);
139             }
140         }
141         return Ok(len);
142     }
143 
144     /// 写入设备操作,把 buf 的数据写入到设备内部 [offset, offset + len) 区间内
write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError>145     fn write_at(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
146         // assert!(len <= buf.len());
147         if len > buf.len() {
148             return Err(SystemError::E2BIG);
149         }
150 
151         let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2());
152         let multi = iter.multiblock;
153 
154         for range in iter {
155             let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节
156             let buf_end = range.origin_end() - offset;
157             let buf_slice = &buf[buf_begin..buf_end];
158             let count: usize = (range.lba_end - range.lba_start).try_into().unwrap();
159             let full = multi && range.is_multi() || !multi && range.is_full();
160 
161             if full {
162                 BlockDevice::write_at(self, range.lba_start, count, buf_slice)?;
163             } else {
164                 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT {
165                     return Err(SystemError::E2BIG);
166                 }
167 
168                 let mut temp = Vec::new();
169                 temp.resize(1usize << self.blk_size_log2(), 0);
170                 // 由于块设备每次读写都是整块的,在不完整写入之前,必须把不完整的地方补全
171                 BlockDevice::read_at(self, range.lba_start, 1, &mut temp[..])?;
172                 // 把数据从临时buffer复制到目标buffer
173                 temp[range.begin..range.end].copy_from_slice(&buf_slice);
174                 BlockDevice::write_at(self, range.lba_start, 1, &temp[..])?;
175             }
176         }
177         return Ok(len);
178     }
179 
180     /// 数据同步
sync(&self) -> Result<(), SystemError>181     fn sync(&self) -> Result<(), SystemError> {
182         BlockDevice::sync(self)
183     }
184 }
185 
186 /// @brief 块设备的迭代器
187 /// @usage 某次操作读/写块设备的[L,R]范围内的字节,
188 ///        那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange
189 pub struct BlockIter {
190     pub begin: usize, // 迭代器的起始位置 -> 块设备的地址 (单位是字节)
191     pub end: usize,
192     pub blk_size_log2: u8,
193     pub multiblock: bool, // 是否启用连续整块同时遍历
194 }
195 
196 /// @brief Range搭配迭代器BlockIter使用,[L,R]区间被分割成多个小的Range
197 ///        Range要么是整块,要么是一块的某一部分
198 /// 细节: range = [begin, end) 左闭右开
199 pub struct BlockRange {
200     pub lba_start: usize, // 起始块的lba_id
201     pub lba_end: usize,   // 终止块的lba_id
202     pub begin: usize, // 起始位置在块内的偏移量, 如果BlockIter启用Multiblock,则是多个块的偏移量
203     pub end: usize,   // 结束位置在块内的偏移量,单位是字节
204     pub blk_size_log2: u8,
205 }
206 
207 impl BlockIter {
208     #[allow(dead_code)]
new(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter209     pub fn new(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
210         return BlockIter {
211             begin: start_addr,
212             end: end_addr,
213             blk_size_log2: blk_size_log2,
214             multiblock: false,
215         };
216     }
new_multiblock(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter217     pub fn new_multiblock(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter {
218         return BlockIter {
219             begin: start_addr,
220             end: end_addr,
221             blk_size_log2: blk_size_log2,
222             multiblock: true,
223         };
224     }
225 
226     /// 获取下一个整块或者不完整的块
next_block(&mut self) -> BlockRange227     pub fn next_block(&mut self) -> BlockRange {
228         let blk_size_log2 = self.blk_size_log2;
229         let blk_size = 1usize << self.blk_size_log2;
230         let lba_id = self.begin / blk_size;
231         let begin = self.begin % blk_size;
232         let end = if lba_id == self.end / blk_size {
233             self.end % blk_size
234         } else {
235             blk_size
236         };
237 
238         self.begin += end - begin;
239 
240         return BlockRange {
241             lba_start: lba_id,
242             lba_end: lba_id + 1,
243             begin: begin,
244             end: end,
245             blk_size_log2: blk_size_log2,
246         };
247     }
248 
249     /// 如果能返回多个连续的整块,则返回;否则调用next_block()返回不完整的块
next_multiblock(&mut self) -> BlockRange250     pub fn next_multiblock(&mut self) -> BlockRange {
251         let blk_size_log2 = self.blk_size_log2;
252         let blk_size = 1usize << self.blk_size_log2;
253         let lba_start = self.begin / blk_size;
254         let lba_end = self.end / blk_size;
255 
256         // 如果不是整块,先返回非整块的小部分
257         if __bytes_to_lba(self.begin, blk_size)
258             != __bytes_to_lba(self.begin + blk_size - 1, blk_size)
259             || lba_start == lba_end
260         {
261             return self.next_block();
262         }
263 
264         let begin = self.begin % blk_size; // 因为是多个整块,这里必然是0
265         let end = __lba_to_bytes(lba_end, blk_size) - self.begin;
266 
267         self.begin += end - begin;
268 
269         return BlockRange {
270             lba_start: lba_start,
271             lba_end: lba_end,
272             begin: begin,
273             end: end,
274             blk_size_log2: blk_size_log2,
275         };
276     }
277 }
278 
279 /// BlockIter 函数实现
280 impl Iterator for BlockIter {
281     type Item = BlockRange;
282 
next(&mut self) -> Option<<Self as Iterator>::Item>283     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
284         if self.begin >= self.end {
285             return None;
286         }
287         if self.multiblock {
288             return Some(self.next_multiblock());
289         } else {
290             return Some(self.next_block());
291         }
292     }
293 }
294 
295 /// BlockRange 函数实现
296 impl BlockRange {
297     #[allow(dead_code)]
is_empty(&self) -> bool298     pub fn is_empty(&self) -> bool {
299         return self.end == self.begin;
300     }
len(&self) -> usize301     pub fn len(&self) -> usize {
302         return self.end - self.begin;
303     }
304     /// 判断是不是整块
is_full(&self) -> bool305     pub fn is_full(&self) -> bool {
306         return self.len() == (1usize << self.blk_size_log2);
307     }
308     /// 判断是不是多个整块连在一起
is_multi(&self) -> bool309     pub fn is_multi(&self) -> bool {
310         return self.len() >= (1usize << self.blk_size_log2)
311             && (self.len() % (1usize << self.blk_size_log2) == 0);
312     }
313     /// 获取 BlockRange 在块设备内部的起始位置 (单位是字节)
origin_begin(&self) -> usize314     pub fn origin_begin(&self) -> usize {
315         return (self.lba_start << self.blk_size_log2) + self.begin;
316     }
317     /// 获取 BlockRange 在块设备内部的结尾位置 (单位是字节)
origin_end(&self) -> usize318     pub fn origin_end(&self) -> usize {
319         return (self.lba_start << self.blk_size_log2) + self.end;
320     }
321 }
322 
323 /// 从字节地址转换到lba id
324 #[inline]
__bytes_to_lba(addr: usize, blk_size: usize) -> BlockId325 pub fn __bytes_to_lba(addr: usize, blk_size: usize) -> BlockId {
326     return addr / blk_size;
327 }
328 
329 /// 从lba id转换到字节地址, 返回lba_id的最左侧字节
330 #[inline]
__lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId331 pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
332     return lba_id * blk_size;
333 }
334