zakhar_azg

Untitled

Dec 12th, 2024
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.15 KB | None | 0 0
  1. use core::{cmp, fmt, iter::Filter, mem, ops::Add};
  2.  
  3. use chrono::{DateTime, Utc};
  4. use static_assertions::const_assert;
  5.  
  6. use ku::{
  7. error::{
  8. Error::{FileExists, FileNotFound, InvalidArgument, NoDisk, NotDirectory, NotFile},
  9. Result,
  10. },
  11. memory::{block, size::Size, Block, Virt},
  12. time,
  13. };
  14. use tracing::debug;
  15.  
  16. use super::{bitmap::Bitmap, block_cache::BlockCache, directory_entry::DirectoryEntry, BLOCK_SIZE};
  17.  
  18. // Used in docs.
  19. #[allow(unused)]
  20. use ku::error::Error;
  21.  
  22.  
  23. // ANCHOR: kind
  24. /// Тип объекта с данными --- [inode](https://en.wikipedia.org/wiki/Inode).
  25. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
  26. #[repr(usize)]
  27. pub enum Kind {
  28. /// Файл.
  29. #[default]
  30. File = 0,
  31.  
  32. /// Директория.
  33. Directory = 1,
  34. }
  35. // ANCHOR_END: kind
  36.  
  37.  
  38. // ANCHOR: inode
  39. /// Метаинформация об объекте с данными --- [inode](https://en.wikipedia.org/wiki/Inode).
  40. #[derive(Clone, Copy, Debug, Default)]
  41. #[repr(C)]
  42. pub(super) struct Inode {
  43. /// Тип объекта с данными --- файл или директория.
  44. kind: Kind,
  45.  
  46. /// Время последней модификации [`Inode`].
  47. modify_time: DateTime<Utc>,
  48.  
  49. /// Размер данных в байтах.
  50. size: usize,
  51.  
  52. /// Лес, отвечающий за отображение блоков [`Inode`]
  53. /// в номера блоков файловой системы.
  54. root_blocks: Forest,
  55. }
  56. // ANCHOR_END: inode
  57.  
  58.  
  59. impl Inode {
  60. /// Инициализирует [`Inode`] заданным типом `kind`.
  61. pub(super) fn init(&mut self, kind: Kind) {
  62. self.kind = kind;
  63. self.modify_time = time::now_ms();
  64. self.size = 0;
  65. self.root_blocks.fill(NO_BLOCK);
  66. }
  67.  
  68.  
  69. /// Тип объекта с данными --- файл или директория.
  70. pub(super) fn kind(&self) -> Kind {
  71. self.kind
  72. }
  73.  
  74.  
  75. /// Удаляет [`Inode`].
  76. pub(super) fn remove(&mut self, block_bitmap: &mut Bitmap) -> Result<()> {
  77. self.set_size(0, block_bitmap)?;
  78. assert!(self.root_blocks.iter().all(|&block| block == NO_BLOCK));
  79.  
  80. Ok(())
  81. }
  82.  
  83.  
  84. /// Размер данных в байтах.
  85. pub(super) fn size(&self) -> usize {
  86. self.size
  87. }
  88.  
  89.  
  90. // ANCHOR: set_size
  91. /// Устанавливает размер данных в байтах.
  92. ///
  93. /// Если файл расширяется, то новые блоки с данными содержат нули.
  94. /// При необходимости выделяет или освобождает блоки через `block_bitmap`.
  95. /// Обновляет время последней модификации [`Inode`].
  96. ///
  97. /// Если новый размер `size` равен нулю, должен освободить все косвенные блоки,
  98. /// используемые в [`Inode::root_blocks`].
  99. pub(super) fn set_size(&mut self, size: usize, block_bitmap: &mut Bitmap) -> Result<()> {
  100. // ANCHOR_END: set_size
  101. let old_block_count = self.size.div_ceil(BLOCK_SIZE);
  102. let new_block_count = size.div_ceil(BLOCK_SIZE);
  103.  
  104. if new_block_count < old_block_count {
  105. for block_idx in new_block_count..old_block_count {
  106. if let Ok(block_entry) = self.block_entry(block_idx, None) {
  107. if *block_entry != NO_BLOCK {
  108. block_bitmap.set_free(*block_entry);
  109. *block_entry = NO_BLOCK;
  110. }
  111. }
  112. }
  113.  
  114. if size == 0 {
  115. for i in 0..self.root_blocks.len() {
  116. if self.root_blocks[i] != NO_BLOCK {
  117. remove_tree(&mut self.root_blocks[i], i, block_bitmap)?;
  118. }
  119. }
  120. }
  121.  
  122. } else if new_block_count > old_block_count {
  123. for block_idx in old_block_count..new_block_count {
  124. if let Ok(block_entry) = self.block_entry(block_idx, Some(block_bitmap)) {
  125. if *block_entry == NO_BLOCK {
  126. *block_entry = block_bitmap.allocate()?;
  127. let block = BlockCache::block(*block_entry)?;
  128. unsafe { block.try_into_mut_slice::<u8>()?.fill(0); }
  129. }
  130. }
  131. }
  132. }
  133.  
  134. self.size = size;
  135. self.modify_time = time::now_ms();
  136. return Ok(());
  137. }
  138.  
  139.  
  140. /// Возвращает максимальный размер в байтах, которые может иметь файл.
  141. pub(super) fn max_size() -> usize {
  142. let max_blocks = leaf_count();
  143.  
  144. max_blocks * BLOCK_SIZE
  145. }
  146.  
  147.  
  148. /// Время последней модификации [`Inode`].
  149. pub(super) fn modify_time(&self) -> DateTime<Utc> {
  150. self.modify_time
  151. }
  152.  
  153.  
  154. /// Находит занятую запись с именем `name` в директории.
  155. ///
  156. /// Возвращает ошибку [`Error::FileNotFound`], если такой записи нет.
  157. pub(super) fn find(&mut self, name: &str) -> Result<&mut DirectoryEntry> {
  158. self.find_entry(name, None).and_then(|entry| {
  159. if entry.is_free() {
  160. Err(FileNotFound)
  161. } else {
  162. Ok(entry)
  163. }
  164. })
  165. }
  166.  
  167.  
  168. // ANCHOR: insert
  169. /// Вставляет в директорию запись с именем `name` и возвращает ссылку на неё.
  170. /// Обновляет время модификации директории.
  171. ///
  172. /// Возвращает ошибку [`Error::FileExists`] если запись с таким именем уже есть.
  173. pub(super) fn insert(
  174. &mut self,
  175. name: &str,
  176. block_bitmap: &mut Bitmap,
  177. ) -> Result<&mut DirectoryEntry> {
  178. // ANCHOR_END: insert
  179. // TODO: your code here.
  180. unimplemented!();
  181. }
  182.  
  183.  
  184. /// Возвращает итератор по занятым записям директории.
  185. pub(super) fn list(&mut self) -> Result<List> {
  186. Ok(List(self.iter()?.filter(|entry| !entry.is_free())))
  187. }
  188.  
  189.  
  190. // ANCHOR: read
  191. /// Читает из файла по смещению `offset` в буфер `buffer` столько байт,
  192. /// сколько остаётся до конца файла или до конца буфера.
  193. ///
  194. /// Возвращает количество прочитанных байт.
  195. /// Если `offset` равен размеру файла, возвращает `0` прочитанных байт.
  196. ///
  197. /// Возвращает ошибки:
  198. ///
  199. /// - [`Error::NotFile`] если [`Inode`] не является файлом.
  200. /// - [`Error::InvalidArgument`] если `offset` превышает размер файла.
  201. pub(super) fn read(&mut self, offset: usize, buffer: &mut [u8]) -> Result<usize> {
  202. // ANCHOR_END: read
  203. debug!("start_reading...");
  204.  
  205. if self.kind != Kind::File {
  206. return Err(Error::NotFile);
  207. }
  208.  
  209. if offset > self.size {
  210. return Err(Error::InvalidArgument);
  211. }
  212.  
  213. let mut bytes_left = self.size - offset;
  214. let mut bytes_read = 0;
  215.  
  216. for block_idx in offset / BLOCK_SIZE ..= self.size / BLOCK_SIZE {
  217. debug!(?block_idx);
  218. let block = self.block(block_idx)?;
  219.  
  220. let block_offset = if block_idx == offset / BLOCK_SIZE {
  221. offset % BLOCK_SIZE
  222. } else {
  223. 0
  224. };
  225.  
  226. let bytes_to_read = core::cmp::min(buffer.len() - bytes_read, BLOCK_SIZE - block_offset);
  227. let bytes_available = core::cmp::min(bytes_left, bytes_to_read);
  228.  
  229. let block_slice = unsafe { block.try_into_slice::<u8>() }?;
  230.  
  231. buffer[bytes_read..bytes_read + bytes_available].copy_from_slice(
  232. &block_slice[block_offset..block_offset + bytes_available],
  233. );
  234.  
  235. bytes_read += bytes_available;
  236. bytes_left -= bytes_available;
  237.  
  238. if bytes_left == 0 || bytes_read == buffer.len() {
  239. break;
  240. }
  241. }
  242.  
  243. return Ok(bytes_read);
  244.  
  245. }
  246.  
  247.  
  248. // ANCHOR: write
  249. /// Записывает в файл по смещению `offset` байты из буфера `buffer`.
  250. /// При необходимости расширяет размер файла.
  251. /// Обновляет время модификации файла.
  252. ///
  253. /// Возвращает количество записанных байт.
  254. /// Если `offset` превышает размер файла, расширяет файл нулями до заданного `offset`.
  255. ///
  256. /// Возвращает ошибку [`Error::NotFile`] если [`Inode`] не является файлом.
  257. pub(super) fn write(
  258. &mut self,
  259. offset: usize,
  260. buffer: &[u8],
  261. block_bitmap: &mut Bitmap,
  262. ) -> Result<usize> {
  263. // ANCHOR_END: write
  264.  
  265. if self.kind != Kind::File {
  266. return Err(Error::NotFile);
  267. }
  268.  
  269. if offset > self.size {
  270. self.set_size(offset, block_bitmap)?;
  271. }
  272.  
  273. let mut bytes_left = buffer.len();
  274. let mut bytes_written = 0;
  275.  
  276. for block_idx in offset / BLOCK_SIZE ..= self.size / BLOCK_SIZE {
  277. let block = self.block(block_idx)?;
  278.  
  279. let block_offset = if block_idx == offset / BLOCK_SIZE {
  280. offset % BLOCK_SIZE
  281. } else {
  282. 0
  283. };
  284.  
  285. let bytes_to_write = core::cmp::min(bytes_left, BLOCK_SIZE - block_offset);
  286.  
  287. let block_slice = unsafe { block.try_into_mut_slice::<u8>() }?;
  288.  
  289. block_slice[block_offset..block_offset + bytes_to_write]
  290. .copy_from_slice(&buffer[bytes_written..bytes_written + bytes_to_write]);
  291.  
  292. bytes_written += bytes_to_write;
  293. bytes_left -= bytes_to_write;
  294.  
  295. if bytes_left == 0 {
  296. break;
  297. }
  298. }
  299. self.modify_time = time::now_ms();
  300. return Ok(bytes_written);
  301. }
  302.  
  303.  
  304. // ANCHOR: find_entry
  305. /// Находит занятую запись с именем `name` в директории.
  306. ///
  307. /// Если такой записи нет, возвращает свободную запись --- [`DirectoryEntry::is_free()`].
  308. /// Если и таких нет, и при этом `block_bitmap` является [`Some`],
  309. /// пробует расширить директорию и вернуть новую свободную запись.
  310. /// Иначе возвращает ошибку [`Error::FileNotFound`].
  311. fn find_entry(
  312. &mut self,
  313. name: &str,
  314. block_bitmap: Option<&mut Bitmap>,
  315. ) -> Result<&mut DirectoryEntry> {
  316. // ANCHOR_END: find_entry
  317. // TODO: your code here.
  318. unimplemented!();
  319. }
  320.  
  321.  
  322. /// Возвращает итератор по всем записям директории, --- и занятым, и свободным.
  323. fn iter(&mut self) -> Result<Iter> {
  324. if self.kind == Kind::Directory {
  325. assert!(self.size % BLOCK_SIZE == 0);
  326.  
  327. Ok(Iter {
  328. block: Block::default(),
  329. block_number: 0,
  330. entry: 0,
  331. inode: self,
  332. })
  333. } else {
  334. Err(NotDirectory)
  335. }
  336. }
  337.  
  338.  
  339. // ANCHOR: block_entry
  340. /// По номеру блока `inode_block_number` внутри данных [`Inode`]
  341. /// возвращает ссылку на запись из метаданных этого [`Inode`].
  342. ///
  343. /// Эта запись предназначена для номера блока на диске,
  344. /// хранящего указанный блок данных [`Inode`].
  345. /// С помощью этого метода происходит отображение смещения внутри данных файла
  346. /// в номер блока на диске, хранящего эти данные.
  347. /// Номер `inode_block_number` равен смещению внутри данных файла,
  348. /// делённому на размер блока [`BLOCK_SIZE`].
  349. ///
  350. /// Если при обходе леса отображения блоков `Inode::root_blocks`
  351. /// встречается не выделенный косвенный блок, пробует выделить его с помощью `block_bitmap`.
  352. /// Если при этом `block_bitmap` равен [`None`], возвращает ошибку [`Error::NoDisk`].
  353. fn block_entry(
  354. &mut self,
  355. inode_block_number: usize,
  356. block_bitmap: Option<&mut Bitmap>,
  357. ) -> Result<&mut usize> {
  358.  
  359. let leaf = inode_block_number;
  360. let coordinates = find_leaf(leaf)?;
  361. traverse(&mut self.root_blocks, coordinates, block_bitmap)
  362. }
  363.  
  364.  
  365. // ANCHOR: block
  366. /// Возвращает блок в памяти блочного кеша,
  367. /// где хранится блок `inode_block_number` внутри данных [`Inode`].
  368. fn block(&mut self, inode_block_number: usize) -> Result<Block<Virt>> {
  369. // ANCHOR_END: block
  370. assert!(inode_block_number < self.size.div_ceil(BLOCK_SIZE));
  371. BlockCache::block(*self.block_entry(inode_block_number, None)?)
  372. }
  373.  
  374.  
  375. /// Расширяет директорию свободными записями на один блок.
  376. fn extend(&mut self, block_bitmap: &mut Bitmap) -> Result<()> {
  377. self.set_size(self.size() + BLOCK_SIZE, block_bitmap)
  378. }
  379. }
  380.  
  381.  
  382. impl fmt::Display for Inode {
  383. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  384. write!(
  385. formatter,
  386. "{{ {:?}, size: {} B = {}, modify: {} }}",
  387. self.kind(),
  388. self.size(),
  389. Size::bytes(self.size()),
  390. self.modify_time(),
  391. )
  392. }
  393. }
  394.  
  395.  
  396. // ANCHOR: iter
  397. /// Итератор по всем записям директории, --- и занятым, и свободным.
  398. pub(super) struct Iter<'a> {
  399. /// Блок в памяти блочного кеша, внутри которого находится текущая позиция итератора.
  400. block: Block<Virt>,
  401.  
  402. /// Номер блока внутри данных [`Inode`] для текущей позиции итератора.
  403. block_number: usize,
  404.  
  405. /// Индекс [`DirectoryEntry`] внутри блока для текущей позиции итератора.
  406. entry: usize,
  407.  
  408. /// [`Inode`] самой директории.
  409. inode: &'a mut Inode,
  410. }
  411. // ANCHOR_END: iter
  412.  
  413.  
  414. impl<'a> Iterator for Iter<'a> {
  415. type Item = &'a mut DirectoryEntry;
  416.  
  417.  
  418. fn next(&mut self) -> Option<Self::Item> {
  419. // TODO: your code here.
  420. unimplemented!();
  421. }
  422. }
  423.  
  424.  
  425. /// Итератор по занятым записям директории.
  426. pub(super) struct List<'a>(Filter<Iter<'a>, fn(&&mut DirectoryEntry) -> bool>);
  427.  
  428.  
  429. impl<'a> Iterator for List<'a> {
  430. type Item = &'a mut DirectoryEntry;
  431.  
  432.  
  433. fn next(&mut self) -> Option<Self::Item> {
  434. self.0.next()
  435. }
  436. }
  437.  
  438.  
  439. // ANCHOR: forest
  440. /// Лес, отвечающий за отображение блоков [`Inode`]
  441. /// в номера блоков файловой системы.
  442. type Forest = [usize; MAX_HEIGHT];
  443. // ANCHOR_END: forest
  444.  
  445.  
  446. // ANCHOR: find_leaf
  447. /// Вспомогательная функция для обхода леса отображения блоков [`Inode`].
  448. /// По заданному количеству `tree_count` деревьев в лесу и номеру блока с данными `leaf_number`
  449. /// выдает кортеж с номером нужного дерева, количеством листьев в этом дереве и номером листа
  450. /// в этом дереве, который соответствует листу `leaf_number` леса.
  451. fn find_leaf(leaf_in_forest: usize) -> Result<LeafCoordinates> {
  452. // ANCHOR_END: find_leaf
  453. let mut remaining_leaves = leaf_in_forest;
  454.  
  455. for tree_height in 0..MAX_HEIGHT {
  456. let leaves_in_tree = leaf_count_in_tree(tree_height);
  457.  
  458. if remaining_leaves < leaves_in_tree {
  459. return Ok(
  460. LeafCoordinates{
  461. tree: tree_height,
  462. leaf: remaining_leaves
  463. }
  464. );
  465. }
  466. remaining_leaves -= leaves_in_tree;
  467. }
  468. return Err(Error::InvalidArgument);
  469. }
  470.  
  471.  
  472. /// Полное количество листьев в лесу [`Forest`] ---
  473. /// максимальное количество блоков в одном [`Inode`].
  474. fn leaf_count() -> usize {
  475. (0..MAX_HEIGHT)
  476. .map(leaf_count_in_tree)
  477. .reduce(Add::add)
  478. .expect("the forest is empty")
  479. }
  480.  
  481.  
  482. /// Количество листьев в дереве высоты `tree_height`.
  483. fn leaf_count_in_tree(tree_height: usize) -> usize {
  484. INDIRECT_BLOCK_ARITY.pow(tree_height.try_into().expect("the tree height is off the chart"))
  485. }
  486.  
  487.  
  488. // ANCHOR: remove_tree
  489. /// Удаляет из леса отображения блоков [`Inode`] дерево или поддерево,
  490. /// на которое указывает запись `node`.
  491. /// Высота поддерева передаётся в `height`.
  492. /// Освобождаемые косвенные блоки передаются в `block_bitmap`.
  493. fn remove_tree(node: &mut usize, height: usize, block_bitmap: &mut Bitmap) -> Result<()> {
  494. if *node == NO_BLOCK {
  495. return Ok(());
  496. }
  497.  
  498. if height > 0 {
  499. let children_block = BlockCache::block(*node)?;
  500. let children_slice = unsafe { children_block.try_into_mut_slice::<usize>() }?;
  501. for children in children_slice.into_iter() {
  502. remove_tree(children, height - 1, block_bitmap)?;
  503. }
  504. }
  505.  
  506. block_bitmap.set_free(*node);
  507. *node = NO_BLOCK;
  508. return Ok(());
  509. }
  510.  
  511.  
  512. // ANCHOR: traverse
  513. /// Обходит лес `forest` в поисках листа с координатами `leaf_coordinates`.
  514. /// Возвращает ссылку на запись с номером соответствующего блока данных [`Inode`],
  515. /// хранящуюся в самом [`Inode`] или в его косвенном блоке.
  516. /// При необходимости выделяет косвенные блоки --- узлы дерева --- из `block_bitmap`.
  517. fn traverse<'a>(
  518. forest: &'a mut Forest,
  519. leaf_coordinates: LeafCoordinates,
  520. mut block_bitmap: Option<&mut Bitmap>,
  521. ) -> Result<&'a mut usize> {
  522. // ANCHOR_END: traverse
  523.  
  524. let root = &mut forest[leaf_coordinates.tree];
  525.  
  526. let mut node = root;
  527.  
  528. let leaf_number = leaf_coordinates.leaf;
  529.  
  530. for level in 0..leaf_coordinates.tree {
  531. let children = next_level(node, &mut block_bitmap)?;
  532. let bin_num = INDIRECT_BLOCK_ARITY.pow((leaf_coordinates.tree - level - 1).try_into().unwrap());
  533. let index = leaf_number.div_floor(bin_num) % INDIRECT_BLOCK_ARITY;
  534. node = &mut children[index];
  535. }
  536.  
  537. return Ok(node);
  538. }
  539.  
  540.  
  541. // ANCHOR: next_level
  542. /// Возвращает срез потомков узла `node` в лесу отображения блоков [`Inode`].
  543. /// При необходимости, то есть когда `*node` равен [`NO_BLOCK`],
  544. /// выделяет косвенный блок для них из `block_bitmap` и заполняет его записями [`NO_BLOCK`].
  545. fn next_level<'a>(
  546. node: &'a mut usize,
  547. block_bitmap: &mut Option<&mut Bitmap>,
  548. ) -> Result<&'a mut [usize]> {
  549. // ANCHOR_END: next_level
  550.  
  551. if *node == NO_BLOCK {
  552. let bitmap = block_bitmap.as_deref_mut().ok_or(NoDisk)?;
  553. *node = bitmap.allocate()?;
  554.  
  555. let children_block = BlockCache::block(*node)?;
  556. let children_slice = unsafe { children_block.try_into_mut_slice::<usize>() }?;
  557. children_slice.fill(NO_BLOCK);
  558. }
  559.  
  560. let children_block = BlockCache::block(*node)?;
  561. let children_slice = unsafe { children_block.try_into_mut_slice::<usize>() }?;
  562. return Ok(children_slice);
  563.  
  564. }
  565.  
  566.  
  567. /// Координаты листа в лесу.
  568. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  569. struct LeafCoordinates {
  570. /// Номер леста в его дереве.
  571. leaf: usize,
  572.  
  573. /// Номер дерева в лесу [`Forest`].
  574. tree: usize,
  575. }
  576.  
  577.  
  578. const_assert!(BLOCK_SIZE % mem::size_of::<usize>() == 0);
  579. const_assert!(BLOCK_SIZE % mem::size_of::<Inode>() == 0);
  580.  
  581.  
  582. /// Арность дерева отображения блоков.
  583. const INDIRECT_BLOCK_ARITY: usize = BLOCK_SIZE / mem::size_of::<usize>();
  584.  
  585. // ANCHOR: max_height
  586. /// Максимальная высота дерева отображения блоков.
  587. const MAX_HEIGHT: usize = 4;
  588. // ANCHOR_END: max_height
  589.  
  590. /// Зарезервированный номер блока, означающий что блок не выделен.
  591. const NO_BLOCK: usize = 0;
  592.  
  593.  
  594. #[doc(hidden)]
  595. pub mod test_scaffolding {
  596. use ku::error::Result;
  597.  
  598. use super::super::test_scaffolding::Bitmap;
  599.  
  600. use super::Kind;
  601.  
  602.  
  603. #[derive(Clone, Copy, Debug, Default)]
  604. pub struct Inode(pub(in super::super) super::Inode);
  605.  
  606.  
  607. impl Inode {
  608. pub fn new(kind: Kind) -> Self {
  609. Self(super::Inode {
  610. kind,
  611. ..Default::default()
  612. })
  613. }
  614.  
  615.  
  616. pub fn block_entry(
  617. &mut self,
  618. inode_block_number: usize,
  619. block_bitmap: &mut Bitmap,
  620. ) -> Result<&mut usize> {
  621. self.0.block_entry(inode_block_number, Some(&mut block_bitmap.0))
  622. }
  623. }
  624. }
  625.  
Advertisement
Add Comment
Please, Sign In to add comment