alloc.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. use super::Ext4;
  2. use crate::constants::*;
  3. use crate::ext4_defs::*;
  4. use crate::format_error;
  5. use crate::prelude::*;
  6. use crate::return_error;
  7. impl Ext4 {
  8. /// Create a new inode, returning the inode and its number
  9. pub(super) fn create_inode(&self, mode: InodeMode) -> Result<InodeRef> {
  10. // Allocate an inode
  11. let is_dir = mode.file_type() == FileType::Directory;
  12. let id = self.alloc_inode(is_dir)?;
  13. // Initialize the inode
  14. let mut inode = Inode::default();
  15. inode.set_mode(mode);
  16. inode.extent_init();
  17. let mut inode_ref = InodeRef::new(id, inode);
  18. // Sync the inode to disk
  19. self.write_inode_with_csum(&mut inode_ref);
  20. trace!("Alloc inode {} ok", inode_ref.id);
  21. Ok(inode_ref)
  22. }
  23. /// Create(initialize) the root inode of the file system
  24. pub(super) fn create_root_inode(&self) -> Result<InodeRef> {
  25. let mut inode = Inode::default();
  26. inode.set_mode(InodeMode::from_type_and_perm(
  27. FileType::Directory,
  28. InodeMode::from_bits_retain(0o755),
  29. ));
  30. inode.extent_init();
  31. let mut root = InodeRef::new(EXT4_ROOT_INO, inode);
  32. let root_self = root.clone();
  33. // Add `.` and `..` entries
  34. self.dir_add_entry(&mut root, &root_self, ".")?;
  35. self.dir_add_entry(&mut root, &root_self, "..")?;
  36. root.inode.set_link_count(2);
  37. self.write_inode_with_csum(&mut root);
  38. Ok(root)
  39. }
  40. /// Free an allocated inode and all data blocks allocated for it
  41. pub(super) fn free_inode(&self, inode: &mut InodeRef) -> Result<()> {
  42. // Free the data blocks allocated for the inode
  43. let pblocks = self.extent_all_data_blocks(&inode);
  44. for pblock in pblocks {
  45. // Deallocate the block
  46. self.dealloc_block(inode, pblock)?;
  47. // Clear the block content
  48. self.write_block(&Block::new(pblock, [0; BLOCK_SIZE]));
  49. }
  50. // Free extent tree
  51. let pblocks = self.extent_all_tree_blocks(&inode);
  52. for pblock in pblocks {
  53. // Deallocate the block
  54. self.dealloc_block(inode, pblock)?;
  55. // Tree blocks are not counted in `inode.block_count`
  56. // Clear the block content
  57. self.write_block(&Block::new(pblock, [0; BLOCK_SIZE]));
  58. }
  59. // Deallocate the inode
  60. self.dealloc_inode(&inode)?;
  61. Ok(())
  62. }
  63. /// Append a data block for an inode, return a pair of (logical block id, physical block id)
  64. ///
  65. /// Only data blocks allocated by `inode_append_block` will be counted in `inode.block_count`.
  66. /// Blocks allocated by calling `alloc_block` directly will not be counted, i.e., blocks
  67. /// allocated for the inode's extent tree.
  68. ///
  69. /// Appending a block does not increase `inode.size`, because `inode.size` records the actual
  70. /// size of the data content, not the number of blocks allocated for it.
  71. ///
  72. /// If the inode is a file, `inode.size` will be increased when writing to end of the file.
  73. /// If the inode is a directory, `inode.size` will be increased when adding a new entry to the
  74. /// newly created block.
  75. pub(super) fn inode_append_block(&self, inode: &mut InodeRef) -> Result<(LBlockId, PBlockId)> {
  76. // The new logical block id
  77. let iblock = inode.inode.block_count() as LBlockId;
  78. // Check the extent tree to get the physical block id
  79. let fblock = self.extent_query_or_create(inode, iblock, 1)?;
  80. // Update block count
  81. inode.inode.set_block_count(inode.inode.block_count() + 1);
  82. self.write_inode_without_csum(inode);
  83. Ok((iblock, fblock))
  84. }
  85. /// Allocate a new physical block for an inode, return the physical block number
  86. pub(super) fn alloc_block(&self, inode: &mut InodeRef) -> Result<PBlockId> {
  87. let mut sb = self.read_super_block();
  88. // Calc block group id
  89. let inodes_per_group = sb.inodes_per_group();
  90. let bgid = ((inode.id - 1) / inodes_per_group) as BlockGroupId;
  91. // Load block group descriptor
  92. let mut bg = self.read_block_group(bgid);
  93. // Load block bitmap
  94. let bitmap_block_id = bg.desc.block_bitmap_block();
  95. let mut bitmap_block = self.read_block(bitmap_block_id);
  96. let mut bitmap = Bitmap::new(&mut bitmap_block.data, 8 * BLOCK_SIZE);
  97. // Find the first free block
  98. let fblock = bitmap
  99. .find_and_set_first_clear_bit(0, 8 * BLOCK_SIZE)
  100. .ok_or(format_error!(
  101. ErrCode::ENOSPC,
  102. "No free blocks in block group {}",
  103. bgid
  104. ))? as PBlockId;
  105. // Set block group checksum
  106. bg.desc.set_block_bitmap_csum(&sb.uuid(), &bitmap);
  107. self.write_block(&bitmap_block);
  108. // Update block group counters
  109. bg.desc
  110. .set_free_blocks_count(bg.desc.get_free_blocks_count() - 1);
  111. self.write_block_group_with_csum(&mut bg);
  112. // Update superblock counters
  113. sb.set_free_blocks_count(sb.free_blocks_count() - 1);
  114. self.write_super_block(&sb);
  115. trace!("Alloc block {} ok", fblock);
  116. Ok(fblock)
  117. }
  118. /// Deallocate a physical block allocated for an inode
  119. pub(super) fn dealloc_block(&self, inode: &mut InodeRef, pblock: PBlockId) -> Result<()> {
  120. let mut sb = self.read_super_block();
  121. // Calc block group id
  122. let inodes_per_group = sb.inodes_per_group();
  123. let bgid = ((inode.id - 1) / inodes_per_group) as BlockGroupId;
  124. // Load block group descriptor
  125. let mut bg = self.read_block_group(bgid);
  126. // Load block bitmap
  127. let bitmap_block_id = bg.desc.block_bitmap_block();
  128. let mut bitmap_block = self.read_block(bitmap_block_id);
  129. let mut bitmap = Bitmap::new(&mut bitmap_block.data, 8 * BLOCK_SIZE);
  130. // Free the block
  131. if bitmap.is_bit_clear(pblock as usize) {
  132. return_error!(ErrCode::EINVAL, "Block {} is already free", pblock);
  133. }
  134. bitmap.clear_bit(pblock as usize);
  135. // Set block group checksum
  136. bg.desc.set_block_bitmap_csum(&sb.uuid(), &bitmap);
  137. self.write_block(&bitmap_block);
  138. // Update block group counters
  139. bg.desc
  140. .set_free_blocks_count(bg.desc.get_free_blocks_count() + 1);
  141. self.write_block_group_with_csum(&mut bg);
  142. // Update superblock counters
  143. sb.set_free_blocks_count(sb.free_blocks_count() + 1);
  144. self.write_super_block(&sb);
  145. trace!("Free block {} ok", pblock);
  146. Ok(())
  147. }
  148. /// Allocate a new inode, returning the inode number.
  149. fn alloc_inode(&self, is_dir: bool) -> Result<InodeId> {
  150. let mut sb = self.read_super_block();
  151. let bg_count = sb.block_group_count();
  152. let mut bgid = 0;
  153. while bgid <= bg_count {
  154. // Load block group descriptor
  155. let mut bg = self.read_block_group(bgid);
  156. // If there are no free inodes in this block group, try the next one
  157. if bg.desc.free_inodes_count() == 0 {
  158. bgid += 1;
  159. continue;
  160. }
  161. // Load inode bitmap
  162. let bitmap_block_id = bg.desc.inode_bitmap_block();
  163. let mut bitmap_block = self.read_block(bitmap_block_id);
  164. let inode_count = sb.inode_count_in_group(bgid) as usize;
  165. let mut bitmap = Bitmap::new(&mut bitmap_block.data, inode_count);
  166. // Find a free inode
  167. let idx_in_bg =
  168. bitmap
  169. .find_and_set_first_clear_bit(0, inode_count)
  170. .ok_or(format_error!(
  171. ErrCode::ENOSPC,
  172. "No free inodes in block group {}",
  173. bgid
  174. ))? as u32;
  175. // Update bitmap in disk
  176. bg.desc.set_inode_bitmap_csum(&sb.uuid(), &bitmap);
  177. self.write_block(&bitmap_block);
  178. // Modify block group counters
  179. bg.desc
  180. .set_free_inodes_count(bg.desc.free_inodes_count() - 1);
  181. if is_dir {
  182. bg.desc.set_used_dirs_count(bg.desc.used_dirs_count() + 1);
  183. }
  184. let mut unused = bg.desc.itable_unused();
  185. let free = inode_count as u32 - unused;
  186. if idx_in_bg >= free {
  187. unused = inode_count as u32 - (idx_in_bg + 1);
  188. bg.desc.set_itable_unused(unused);
  189. }
  190. self.write_block_group_with_csum(&mut bg);
  191. // Update superblock counters
  192. sb.set_free_inodes_count(sb.free_inodes_count() - 1);
  193. self.write_super_block(&sb);
  194. // Compute the absolute i-node number
  195. let inodes_per_group = sb.inodes_per_group();
  196. let inode_id = bgid * inodes_per_group + (idx_in_bg + 1);
  197. return Ok(inode_id);
  198. }
  199. trace!("no free inode");
  200. return_error!(ErrCode::ENOSPC, "No free inodes in block group {}", bgid);
  201. }
  202. /// Free an inode
  203. fn dealloc_inode(&self, inode_ref: &InodeRef) -> Result<()> {
  204. let mut sb = self.read_super_block();
  205. // Calc block group id and index in block group
  206. let inodes_per_group = sb.inodes_per_group();
  207. let bgid = ((inode_ref.id - 1) / inodes_per_group) as BlockGroupId;
  208. let idx_in_bg = (inode_ref.id - 1) % inodes_per_group;
  209. // Load block group descriptor
  210. let mut bg = self.read_block_group(bgid);
  211. // Load inode bitmap
  212. let bitmap_block_id = bg.desc.inode_bitmap_block();
  213. let mut bitmap_block = self.read_block(bitmap_block_id);
  214. let inode_count = sb.inode_count_in_group(bgid) as usize;
  215. let mut bitmap = Bitmap::new(&mut bitmap_block.data, inode_count);
  216. // Free the inode
  217. if bitmap.is_bit_clear(idx_in_bg as usize) {
  218. return_error!(
  219. ErrCode::EINVAL,
  220. "Inode {} is already free in block group {}",
  221. inode_ref.id,
  222. bgid
  223. );
  224. }
  225. bitmap.clear_bit(idx_in_bg as usize);
  226. // Update bitmap in disk
  227. bg.desc.set_inode_bitmap_csum(&sb.uuid(), &bitmap);
  228. self.write_block(&bitmap_block);
  229. // Update block group counters
  230. bg.desc
  231. .set_free_inodes_count(bg.desc.free_inodes_count() + 1);
  232. if inode_ref.inode.is_dir() {
  233. bg.desc.set_used_dirs_count(bg.desc.used_dirs_count() - 1);
  234. }
  235. bg.desc.set_itable_unused(bg.desc.itable_unused() + 1);
  236. self.write_block_group_with_csum(&mut bg);
  237. // Update superblock counters
  238. sb.set_free_inodes_count(sb.free_inodes_count() - 1);
  239. self.write_super_block(&sb);
  240. Ok(())
  241. }
  242. }