cached_block_device.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. use alloc::{boxed::Box, vec::Vec};
  2. use hashbrown::HashMap;
  3. use log::debug;
  4. use crate::{driver::base::block::block_device::BlockId, libs::rwlock::RwLock};
  5. use super::{
  6. cache_block::{CacheBlock, CacheBlockAddr},
  7. cache_iter::{BlockIter, FailData},
  8. BlockCacheError, BLOCK_SIZE, BLOCK_SIZE_LOG, CACHE_THRESHOLD,
  9. };
  10. static mut CSPACE: Option<LockedCacheSpace> = None;
  11. static mut CMAPPER: Option<LockedCacheMapper> = None;
  12. /// # 结构功能
  13. /// 该结构体向外提供BlockCache服务
  14. pub struct BlockCache;
  15. #[allow(static_mut_refs)]
  16. unsafe fn mapper() -> Result<&'static mut LockedCacheMapper, BlockCacheError> {
  17. unsafe {
  18. match &mut CMAPPER {
  19. Some(x) => return Ok(x),
  20. None => return Err(BlockCacheError::StaticParameterError),
  21. }
  22. };
  23. }
  24. #[allow(static_mut_refs)]
  25. unsafe fn space() -> Result<&'static mut LockedCacheSpace, BlockCacheError> {
  26. unsafe {
  27. match &mut CSPACE {
  28. Some(x) => return Ok(x),
  29. None => return Err(BlockCacheError::StaticParameterError),
  30. }
  31. };
  32. }
  33. impl BlockCache {
  34. /// # 函数的功能
  35. /// 初始化BlockCache需要的结构体
  36. pub fn init() {
  37. unsafe {
  38. CSPACE = Some(LockedCacheSpace::new(CacheSpace::new()));
  39. CMAPPER = Some(LockedCacheMapper::new(CacheMapper::new()));
  40. }
  41. debug!("BlockCache Initialized!");
  42. }
  43. /// # 函数的功能
  44. /// 使用blockcache进行对块设备进行连续块的读操作
  45. ///
  46. /// ## 参数:
  47. /// - 'lba_id_start' :连续块的起始块的lba_id
  48. /// - 'count' :从连续块算起需要读多少块
  49. /// - 'buf' :读取出来的数据存放在buf中
  50. ///
  51. /// ## 返回值:
  52. /// - Ok(usize) :表示读取块的个数
  53. /// - Err(BlockCacheError::BlockFaultError) :缺块的情况下,返回读取失败的块的数据,利用该返回值可以帮助blockcache插入读取失败的块值(见insert函数)
  54. /// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题,这种异常会在block_device中得到处理
  55. pub fn read(
  56. lba_id_start: BlockId,
  57. count: usize,
  58. buf: &mut [u8],
  59. ) -> Result<usize, BlockCacheError> {
  60. // 生成一个块迭代器(BlockIter),它可以迭代地给出所有需要块的数据,其中就包括lba_id
  61. let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
  62. // 调用检查函数,检查有无缺块,如果没有就可以获得所有块的Cache地址。如果失败了就直接返回FailData向量
  63. let cache_block_addr = Self::check_able_to_read(block_iter)?;
  64. // 块地址vec的长度应当等于块迭代器的大小
  65. assert!(cache_block_addr.len() == block_iter.count());
  66. // 迭代地读取cache并写入到buf中
  67. for (index, _) in block_iter.enumerate() {
  68. Self::read_one_block(cache_block_addr[index], index, buf)?;
  69. }
  70. return Ok(count);
  71. }
  72. /// # 函数的功能
  73. /// 检查cache中是否有缺块的函数
  74. ///
  75. /// ## 参数:
  76. /// - 'block_iter' :需要检查的块迭代器(因为块迭代器包含了需要读块的信息,所以传入块迭代器)
  77. ///
  78. /// ## 返回值:
  79. /// - Ok(Vec<CacheBlockAddr>) :如果成功了,那么函数会返回每个块的Cache地址,利用Cache地址就可以访问Cache了
  80. /// - Err(BlockCacheError::BlockFaultError) :如果发现了缺块,那么我们会返回所有缺块的信息(即FailData)
  81. /// - Err(BlockCacheError::____) :不缺块的情况往往是初始化或者其他问题
  82. fn check_able_to_read(block_iter: BlockIter) -> Result<Vec<CacheBlockAddr>, BlockCacheError> {
  83. // 存放缺块信息的向量
  84. let mut fail_ans = vec![];
  85. // 存放命中块地址的向量
  86. let mut success_ans = vec![];
  87. // 获取mapper
  88. let mapper = unsafe { mapper()? };
  89. for (index, i) in block_iter.enumerate() {
  90. // 在mapper中寻找块的lba_id,判断是否命中
  91. match mapper.find(i.lba_id()) {
  92. Some(x) => {
  93. success_ans.push(x);
  94. continue;
  95. }
  96. // 缺块就放入fail_ans
  97. None => fail_ans.push(FailData::new(i.lba_id(), index)),
  98. // 缺块不break的原因是,我们需要把所有缺块都找出来,这样才能补上缺块
  99. }
  100. }
  101. // 只要有缺块就认为cache失败,因为需要补块就需要进行io操作
  102. if !fail_ans.is_empty() {
  103. return Err(BlockCacheError::BlockFaultError(fail_ans));
  104. } else {
  105. return Ok(success_ans);
  106. }
  107. }
  108. /// # 函数的功能
  109. /// 在cache中读取一个块的数据并放置于缓存的指定位置
  110. ///
  111. /// ## 参数:
  112. /// - 'cache_block_addr' :表示需要读取的cache块的地址
  113. /// - 'position' :表示该块的数据需要放置在buf的哪个位置,比如position为2,那么读出的数据将放置在buf\[1024..1536\](这里假设块大小是512)
  114. /// - 'buf' :块数据的缓存
  115. ///
  116. /// ## 返回值:
  117. /// - Ok(usize) :表示读取了多少个字节
  118. /// - Err(BlockCacheError) :如果输入的cache_block_addr超过了cache的容量,那么将返回Err(由于目前的cache不支持动态变化上限,所以可能出现这种错误;而实际上,由于Cache的地址是由frame_selector给出的,所以正确实现的frame_selector理论上不会出现这种错误)
  119. fn read_one_block(
  120. cache_block_addr: CacheBlockAddr,
  121. position: usize,
  122. buf: &mut [u8],
  123. ) -> Result<usize, BlockCacheError> {
  124. let space = unsafe { space()? };
  125. space.read(cache_block_addr, position, buf)
  126. }
  127. /// # 函数的功能
  128. /// 根据缺块的数据和io获得的数据,向cache中补充块数据
  129. ///
  130. /// ## 参数:
  131. /// - 'f_data_vec' :这里输入的一般是从read函数中返回的缺块数据
  132. /// - 'data' :经过一次io后获得的数据
  133. ///
  134. /// ## 返回值:
  135. /// Ok(usize) :表示补上缺页的个数
  136. /// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
  137. pub fn insert(f_data_vec: Vec<FailData>, data: &[u8]) -> Result<usize, BlockCacheError> {
  138. let count = f_data_vec.len();
  139. for i in f_data_vec {
  140. let index = i.index();
  141. Self::insert_one_block(
  142. i.lba_id(),
  143. data[index * BLOCK_SIZE..(index + 1) * BLOCK_SIZE].to_vec(),
  144. )?;
  145. }
  146. Ok(count)
  147. }
  148. /// # 函数的功能
  149. /// 将一个块数据插入到cache中
  150. ///
  151. /// ## 参数:
  152. /// - 'lba_id' :表明该块对应的lba_id,用于建立映射
  153. /// - 'data' :传入的数据
  154. ///
  155. /// ## 返回值:
  156. /// Ok(()):表示插入成功
  157. /// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
  158. fn insert_one_block(lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
  159. let space = unsafe { space()? };
  160. space.insert(lba_id, data)
  161. }
  162. /// # 函数的功能
  163. /// 立即回写,这里仅仅作为取消映射的方法,并没有真正写入到cache的功能
  164. ///
  165. /// ## 参数:
  166. /// - 'lba_id_start' :需要读取的连续块的起始块
  167. /// - 'count' :需要读取块的个数
  168. /// - '_data' :目前没有写入功能,该参数暂时无用
  169. ///
  170. /// ## 返回值:
  171. /// Ok(usize) :表示写入了多少个块
  172. /// Err(BlockCacheError) :这里产生错误的原因只有插入时还没有初始化
  173. pub fn immediate_write(
  174. lba_id_start: BlockId,
  175. count: usize,
  176. _data: &[u8],
  177. ) -> Result<usize, BlockCacheError> {
  178. let mapper = unsafe { mapper()? };
  179. let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
  180. for i in block_iter {
  181. mapper.remove(i.lba_id());
  182. }
  183. Ok(count)
  184. }
  185. }
  186. struct LockedCacheSpace(RwLock<CacheSpace>);
  187. impl LockedCacheSpace {
  188. pub fn new(space: CacheSpace) -> Self {
  189. LockedCacheSpace(RwLock::new(space))
  190. }
  191. pub fn read(
  192. &self,
  193. addr: CacheBlockAddr,
  194. position: usize,
  195. buf: &mut [u8],
  196. ) -> Result<usize, BlockCacheError> {
  197. self.0.read().read(addr, position, buf)
  198. }
  199. pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
  200. todo!()
  201. }
  202. pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
  203. unsafe { self.0.get_mut().insert(lba_id, data) }
  204. }
  205. }
  206. /// # 结构功能
  207. /// 管理Cache空间的结构体
  208. struct CacheSpace {
  209. /// 用于存放CacheBlock,是Cache数据的实际存储空间的向量
  210. root: Vec<CacheBlock>,
  211. /// 在块换出换入时,用于选择替换块的结构体
  212. frame_selector: Box<dyn FrameSelector>,
  213. }
  214. impl CacheSpace {
  215. pub fn new() -> Self {
  216. Self {
  217. root: Vec::new(),
  218. // 如果要修改替换算法,可以设计一个结构体实现FrameSelector trait,再在这里替换掉SimpleFrameSelector
  219. frame_selector: Box::new(SimpleFrameSelector::new()),
  220. }
  221. }
  222. /// # 函数的功能
  223. /// 将一个块的数据写入到buf的指定位置
  224. ///
  225. /// ## 参数:
  226. /// - 'addr' :请求块在Cache中的地址
  227. /// - 'position' :表示需要将Cache放入buf中的位置,例如:若position为1,则块的数据放入buf\[512..1024\]
  228. /// - 'buf' :存放数据的buf
  229. ///
  230. /// ## 返回值:
  231. /// Some(usize):表示读取的字节数(这里默认固定为BLOCK_SIZE)
  232. /// Err(BlockCacheError):如果你输入地址大于cache的最大上限,那么就返回InsufficientCacheSpace
  233. pub fn read(
  234. &self,
  235. addr: CacheBlockAddr,
  236. position: usize,
  237. buf: &mut [u8],
  238. ) -> Result<usize, BlockCacheError> {
  239. if addr > self.frame_selector.size() {
  240. return Err(BlockCacheError::InsufficientCacheSpace);
  241. } else {
  242. // CacheBlockAddr就是用于给root寻址的
  243. return self.root[addr]
  244. .data(&mut buf[position * BLOCK_SIZE..(position + 1) * BLOCK_SIZE]);
  245. }
  246. }
  247. /// # 函数的功能
  248. /// 向cache空间中写入的函数,目前尚未实现
  249. pub fn _write(&mut self, _addr: CacheBlockAddr, _data: CacheBlock) -> Option<()> {
  250. todo!()
  251. }
  252. /// # 函数的功能
  253. /// 向cache中插入一个块并建立lba_id到块之间的映射
  254. ///
  255. /// ## 参数:
  256. /// - 'lba_id' :表明你插入的块的lba_id,用于建立映射
  257. /// - 'data' :要插入块的数据
  258. ///
  259. /// ## 返回值:
  260. /// Ok(())
  261. pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
  262. // CacheBlock是cached block的基本单位,这里使用data生成一个CacheBlock用于向Cache空间中插入块
  263. let data_block = CacheBlock::from_data(lba_id, data);
  264. let mapper = unsafe { mapper()? };
  265. // 这里我设计了cache的一个threshold,如果不超过阈值就可以append,否则只能替换
  266. if self.frame_selector.can_append() {
  267. // 这是append的操作逻辑:
  268. // 从frame_selector获得一个CacheBlockAddr
  269. let index = self.frame_selector.index_append();
  270. // 直接将块push进去就可以,因为现在是append操作
  271. self.root.push(data_block);
  272. assert!(index == self.root.len() - 1);
  273. // 建立mapper的映射
  274. mapper.insert(lba_id, index);
  275. Ok(())
  276. } else {
  277. // 这是replace的操作逻辑
  278. // 从frame_selector获得一个CacheBlockAddr,这次是它替换出来的
  279. let index = self.frame_selector.index_replace();
  280. // 获取被替换的块的lba_id,待会用于取消映射
  281. let removed_id = self.root[index].lba_id();
  282. // 直接替换原本的块,由于被替换的块没有引用了,所以会被drop
  283. self.root[index] = data_block;
  284. // 建立映射插入块的映射
  285. mapper.insert(lba_id, index);
  286. // 取消被替换块的映射
  287. mapper.remove(removed_id);
  288. Ok(())
  289. }
  290. }
  291. }
  292. struct LockedCacheMapper {
  293. lock: RwLock<CacheMapper>,
  294. }
  295. impl LockedCacheMapper {
  296. pub fn new(inner: CacheMapper) -> Self {
  297. Self {
  298. lock: RwLock::new(inner),
  299. }
  300. }
  301. pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
  302. unsafe { self.lock.get_mut().insert(lba_id, caddr) }
  303. }
  304. pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
  305. self.lock.read().find(lba_id)
  306. }
  307. pub fn remove(&mut self, lba_id: BlockId) {
  308. unsafe { self.lock.get_mut().remove(lba_id) }
  309. }
  310. }
  311. /// # 结构功能
  312. /// 该结构体用于建立lba_id到cached块的映射
  313. struct CacheMapper {
  314. // 执行键值对操作的map
  315. map: HashMap<BlockId, CacheBlockAddr>,
  316. }
  317. impl CacheMapper {
  318. pub fn new() -> Self {
  319. Self {
  320. map: HashMap::new(),
  321. }
  322. }
  323. /// # 函数的功能
  324. /// 插入操作
  325. pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
  326. self.map.insert(lba_id, caddr)?;
  327. Some(())
  328. }
  329. /// # 函数的功能
  330. /// 查找操作
  331. #[inline]
  332. pub fn find(&self, lba_id: BlockId) -> Option<CacheBlockAddr> {
  333. Some(*self.map.get(&lba_id)?)
  334. }
  335. /// # 函数的功能
  336. /// 去除操作
  337. pub fn remove(&mut self, lba_id: BlockId) {
  338. self.map.remove(&lba_id);
  339. }
  340. }
  341. /// # 结构功能
  342. /// 该trait用于实现块的换入换出算法,需要设计替换算法只需要实现该trait即可
  343. trait FrameSelector {
  344. /// # 函数的功能
  345. /// 给出append操作的index(理论上,如果cache没满,就不需要换出块,就可以使用append操作)
  346. fn index_append(&mut self) -> CacheBlockAddr;
  347. /// # 函数的功能
  348. /// 给出replace操作后的index
  349. fn index_replace(&mut self) -> CacheBlockAddr;
  350. /// # 函数的功能
  351. /// 判断是否可以append
  352. fn can_append(&self) -> bool;
  353. /// # 函数的功能
  354. /// 获取size
  355. fn size(&self) -> usize;
  356. }
  357. /// # 结构功能
  358. /// 该结构体用于管理块的换入换出过程中,CacheBlockAddr的选择,替换算法在这里实现
  359. struct SimpleFrameSelector {
  360. // 表示BlockCache的阈值,即最大可以存放多少块,这里目前还不支持动态变化
  361. threshold: usize,
  362. // 表示使用过的块帧的数量
  363. size: usize,
  364. // 这里使用从头至尾的替换算法,其替换策略为0,1,2,...,threshold,0,1...以此类推(该算法比FIFO还要简陋,后面可以再实现别的:)
  365. current: usize,
  366. }
  367. impl SimpleFrameSelector {
  368. pub fn new() -> Self {
  369. Self {
  370. threshold: CACHE_THRESHOLD * (1 << (20 - BLOCK_SIZE_LOG)),
  371. size: 0,
  372. current: 0,
  373. }
  374. }
  375. }
  376. impl FrameSelector for SimpleFrameSelector {
  377. fn index_append(&mut self) -> CacheBlockAddr {
  378. let ans = self.current;
  379. self.size += 1;
  380. self.current += 1;
  381. self.current %= self.threshold;
  382. return ans;
  383. }
  384. fn index_replace(&mut self) -> CacheBlockAddr {
  385. let ans = self.current;
  386. self.current += 1;
  387. self.current %= self.threshold;
  388. return ans;
  389. }
  390. fn can_append(&self) -> bool {
  391. self.size < self.threshold
  392. }
  393. fn size(&self) -> usize {
  394. self.size
  395. }
  396. }