alloc.rs 12 KB

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