block_group.rs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. //!# The Defination of Ext4 Block Group Description
  2. //!
  3. //! Block Group Descriptor is the second field of Ext4 Block Group.
  4. //!
  5. //! | Super Block | Group Descriptor | Reserved GDT Blocks |
  6. //! | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
  7. //!
  8. //! See [`super`] for more information.
  9. use super::crc::*;
  10. use super::Bitmap;
  11. use super::BlockDevice;
  12. use super::Superblock;
  13. use crate::constants::*;
  14. use crate::prelude::*;
  15. use crate::AsBytes;
  16. #[derive(Debug, Default, Clone, Copy)]
  17. #[repr(C, packed)]
  18. pub struct BlockGroupDesc {
  19. block_bitmap_lo: u32, // 块位图块
  20. inode_bitmap_lo: u32, // 节点位图块
  21. inode_table_first_block_lo: u32, // 节点表块
  22. free_blocks_count_lo: u16, // 空闲块数
  23. free_inodes_count_lo: u16, // 空闲节点数
  24. used_dirs_count_lo: u16, // 目录数
  25. flags: u16, // EXT4_BG_flags (INODE_UNINIT, etc)
  26. exclude_bitmap_lo: u32, // 快照排除位图
  27. block_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+bbitmap) LE
  28. inode_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+ibitmap) LE
  29. itable_unused_lo: u16, // 未使用的节点数
  30. checksum: u16, // crc16(sb_uuid+group+desc)
  31. block_bitmap_hi: u32, // 块位图块 MSB
  32. inode_bitmap_hi: u32, // 节点位图块 MSB
  33. inode_table_first_block_hi: u32, // 节点表块 MSB
  34. free_blocks_count_hi: u16, // 空闲块数 MSB
  35. free_inodes_count_hi: u16, // 空闲节点数 MSB
  36. used_dirs_count_hi: u16, // 目录数 MSB
  37. itable_unused_hi: u16, // 未使用的节点数 MSB
  38. exclude_bitmap_hi: u32, // 快照排除位图 MSB
  39. block_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+bbitmap) BE
  40. inode_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+ibitmap) BE
  41. reserved: u32, // 填充
  42. }
  43. impl AsBytes for BlockGroupDesc {}
  44. impl BlockGroupDesc {
  45. pub fn block_bitmap_block(&self, s: &Superblock) -> PBlockId {
  46. let mut v = self.block_bitmap_lo as u64;
  47. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  48. v |= (self.block_bitmap_hi as u64) << 32;
  49. }
  50. v
  51. }
  52. pub fn inode_bitmap_block(&self, s: &Superblock) -> PBlockId {
  53. let mut v = self.inode_bitmap_lo as u64;
  54. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  55. v |= (self.inode_bitmap_hi as u64) << 32;
  56. }
  57. v
  58. }
  59. pub fn itable_unused(&mut self, s: &Superblock) -> u32 {
  60. let mut v = self.itable_unused_lo as u32;
  61. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  62. v |= ((self.itable_unused_hi as u64) << 32) as u32;
  63. }
  64. v
  65. }
  66. pub fn used_dirs_count(&self, s: &Superblock) -> u32 {
  67. let mut v = self.used_dirs_count_lo as u32;
  68. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  69. v |= ((self.used_dirs_count_hi as u64) << 32) as u32;
  70. }
  71. v
  72. }
  73. pub fn set_used_dirs_count(&mut self, s: &Superblock, cnt: u32) {
  74. self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
  75. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  76. self.itable_unused_hi = (cnt >> 16) as u16;
  77. }
  78. }
  79. pub fn set_itable_unused(&mut self, s: &Superblock, cnt: u32) {
  80. self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
  81. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  82. self.itable_unused_hi = (cnt >> 16) as u16;
  83. }
  84. }
  85. pub fn set_free_inodes_count(&mut self, s: &Superblock, cnt: u32) {
  86. self.free_inodes_count_lo = ((cnt << 16) >> 16) as u16;
  87. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  88. self.free_inodes_count_hi = (cnt >> 16) as u16;
  89. }
  90. }
  91. pub fn free_inodes_count(&self) -> u32 {
  92. ((self.free_inodes_count_hi as u32) << 16) | self.free_inodes_count_lo as u32
  93. }
  94. pub fn inode_table_first_block(&self) -> PBlockId {
  95. ((self.inode_table_first_block_hi as u64) << 32) | self.inode_table_first_block_lo as u64
  96. }
  97. pub fn get_free_blocks_count(&self) -> u64 {
  98. let mut v = self.free_blocks_count_lo as u64;
  99. if self.free_blocks_count_hi != 0 {
  100. v |= (self.free_blocks_count_hi as u64) << 32;
  101. }
  102. v
  103. }
  104. pub fn set_free_blocks_count(&mut self, cnt: u64) {
  105. self.free_blocks_count_lo = ((cnt << 32) >> 32) as u16;
  106. self.free_blocks_count_hi = (cnt >> 32) as u16;
  107. }
  108. pub fn calc_inode_bitmap_csum(bitmap: &Bitmap, s: &Superblock) -> u32 {
  109. let inodes_per_group = s.inodes_per_group();
  110. let uuid = s.uuid();
  111. let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
  112. csum = ext4_crc32c(csum, bitmap.as_raw(), (inodes_per_group + 7) / 8);
  113. csum
  114. }
  115. pub fn calc_block_bitmap_csum(bitmap: &Bitmap, s: &Superblock) -> u32 {
  116. let blocks_per_group = s.blocks_per_group();
  117. let uuid = s.uuid();
  118. let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
  119. csum = ext4_crc32c(csum, bitmap.as_raw(), (blocks_per_group / 8) as u32);
  120. csum
  121. }
  122. pub fn set_inode_bitmap_csum(&mut self, s: &Superblock, bitmap: &Bitmap) {
  123. let desc_size = s.desc_size();
  124. let csum = Self::calc_inode_bitmap_csum(&bitmap, s);
  125. let lo_csum = (csum & 0xFFFF).to_le();
  126. let hi_csum = (csum >> 16).to_le();
  127. if (s.features_read_only() & 0x400) >> 10 == 0 {
  128. return;
  129. }
  130. self.inode_bitmap_csum_lo = lo_csum as u16;
  131. if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
  132. self.inode_bitmap_csum_hi = hi_csum as u16;
  133. }
  134. }
  135. pub fn set_block_bitmap_csum(&mut self, s: &Superblock, bitmap: &Bitmap) {
  136. let desc_size = s.desc_size();
  137. let csum = Self::calc_block_bitmap_csum(&bitmap, s);
  138. let lo_csum = (csum & 0xFFFF).to_le();
  139. let hi_csum = (csum >> 16).to_le();
  140. if (s.features_read_only() & 0x400) >> 10 == 0 {
  141. return;
  142. }
  143. self.block_bitmap_csum_lo = lo_csum as u16;
  144. if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
  145. self.block_bitmap_csum_hi = hi_csum as u16;
  146. }
  147. }
  148. }
  149. /// A combination of a `BlockGroupDesc` and its id
  150. #[derive(Debug)]
  151. pub struct BlockGroupRef {
  152. /// The block group id
  153. pub id: BlockGroupId,
  154. /// The block group descriptor
  155. pub desc: BlockGroupDesc,
  156. }
  157. impl BlockGroupRef {
  158. /// Load a block group descriptor from the disk
  159. pub fn load_from_disk(
  160. block_device: Arc<dyn BlockDevice>,
  161. super_block: &Superblock,
  162. block_group_id: BlockGroupId,
  163. ) -> Self {
  164. let (block_id, offset) = Self::disk_pos(super_block, block_group_id);
  165. let block = block_device.read_block(block_id as PBlockId);
  166. let desc = block.read_offset_as::<BlockGroupDesc>(offset);
  167. Self {
  168. id: block_group_id,
  169. desc,
  170. }
  171. }
  172. /// Find the position of a block group descriptor in the block device.
  173. /// Return the block id and the offset within the block.
  174. fn disk_pos(s: &Superblock, block_group_id: BlockGroupId) -> (PBlockId, usize) {
  175. let desc_per_block = BLOCK_SIZE as u32 / s.desc_size() as u32;
  176. let block_id = s.first_data_block() + block_group_id / desc_per_block + 1;
  177. let offset = (block_group_id % desc_per_block) * s.desc_size() as u32;
  178. (block_id as PBlockId, offset as usize)
  179. }
  180. pub fn sync_to_disk_without_csum(
  181. &self,
  182. block_device: Arc<dyn BlockDevice>,
  183. super_block: &Superblock,
  184. ) {
  185. let (block_id, offset) = Self::disk_pos(super_block, self.id);
  186. let mut block = block_device.read_block(block_id as PBlockId);
  187. block.write_offset_as(offset, &self.desc);
  188. block.sync_to_disk(block_device);
  189. }
  190. pub fn sync_to_disk_with_csum(
  191. &mut self,
  192. block_device: Arc<dyn BlockDevice>,
  193. super_block: &Superblock,
  194. ) {
  195. self.set_checksum(super_block);
  196. self.sync_to_disk_without_csum(block_device, super_block);
  197. }
  198. pub fn set_checksum(&mut self, super_block: &Superblock) {
  199. let desc_size = super_block.desc_size();
  200. // uuid checksum
  201. let mut checksum = ext4_crc32c(
  202. EXT4_CRC32_INIT,
  203. &super_block.uuid(),
  204. super_block.uuid().len() as u32,
  205. );
  206. // bgid checksum
  207. checksum = ext4_crc32c(checksum, &self.id.to_le_bytes(), 4);
  208. // cast self to &[u8]
  209. let self_bytes =
  210. unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, 0x40 as usize) };
  211. // bg checksum
  212. checksum = ext4_crc32c(checksum, self_bytes, desc_size as u32);
  213. let crc = (checksum & 0xFFFF) as u16;
  214. self.desc.checksum = crc;
  215. }
  216. }