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