device.rs 13 KB

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