block_group.rs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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::Ext4Superblock;
  13. use crate::constants::*;
  14. use crate::prelude::*;
  15. #[derive(Debug, Default, Clone, Copy)]
  16. #[repr(C, packed)]
  17. pub struct Ext4BlockGroupDesc {
  18. block_bitmap_lo: u32, // 块位图块
  19. inode_bitmap_lo: u32, // 节点位图块
  20. inode_table_first_block_lo: u32, // 节点表块
  21. free_blocks_count_lo: u16, // 空闲块数
  22. free_inodes_count_lo: u16, // 空闲节点数
  23. used_dirs_count_lo: u16, // 目录数
  24. flags: u16, // EXT4_BG_flags (INODE_UNINIT, etc)
  25. exclude_bitmap_lo: u32, // 快照排除位图
  26. block_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+bbitmap) LE
  27. inode_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+ibitmap) LE
  28. itable_unused_lo: u16, // 未使用的节点数
  29. checksum: u16, // crc16(sb_uuid+group+desc)
  30. block_bitmap_hi: u32, // 块位图块 MSB
  31. inode_bitmap_hi: u32, // 节点位图块 MSB
  32. inode_table_first_block_hi: u32, // 节点表块 MSB
  33. free_blocks_count_hi: u16, // 空闲块数 MSB
  34. free_inodes_count_hi: u16, // 空闲节点数 MSB
  35. used_dirs_count_hi: u16, // 目录数 MSB
  36. itable_unused_hi: u16, // 未使用的节点数 MSB
  37. exclude_bitmap_hi: u32, // 快照排除位图 MSB
  38. block_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+bbitmap) BE
  39. inode_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+ibitmap) BE
  40. reserved: u32, // 填充
  41. }
  42. impl TryFrom<&[u8]> for Ext4BlockGroupDesc {
  43. type Error = u64;
  44. fn try_from(data: &[u8]) -> core::result::Result<Self, u64> {
  45. let data = &data[..size_of::<Ext4BlockGroupDesc>()];
  46. Ok(unsafe { core::ptr::read(data.as_ptr() as *const _) })
  47. }
  48. }
  49. impl Ext4BlockGroupDesc {
  50. pub fn load(
  51. block_device: Arc<dyn BlockDevice>,
  52. super_block: &Ext4Superblock,
  53. block_group_id: usize,
  54. ) -> core::result::Result<Self, u64> {
  55. let dsc_cnt = BLOCK_SIZE / super_block.desc_size() as usize;
  56. let dsc_id = block_group_id / dsc_cnt;
  57. let first_data_block = super_block.first_data_block();
  58. let block_id = first_data_block as usize + dsc_id + 1;
  59. let offset = (block_group_id % dsc_cnt) * super_block.desc_size() as usize;
  60. let data = block_device.read_offset(block_id * BLOCK_SIZE);
  61. let block_group_data =
  62. &data[offset as usize..offset as usize + size_of::<Ext4BlockGroupDesc>()];
  63. let bg = Ext4BlockGroupDesc::try_from(block_group_data);
  64. bg
  65. }
  66. pub fn get_block_bitmap_block(&self, s: &Ext4Superblock) -> u64 {
  67. let mut v = self.block_bitmap_lo as u64;
  68. let desc_size = s.desc_size();
  69. if desc_size > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  70. v |= (self.block_bitmap_hi as u64) << 32;
  71. }
  72. v
  73. }
  74. pub fn get_inode_bitmap_block(&self, s: &Ext4Superblock) -> u64 {
  75. let mut v = self.inode_bitmap_lo as u64;
  76. let desc_size = s.desc_size();
  77. if desc_size > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  78. v |= (self.inode_bitmap_hi as u64) << 32;
  79. }
  80. v
  81. }
  82. pub fn get_itable_unused(&mut self, s: &Ext4Superblock) -> u32 {
  83. let mut v = self.itable_unused_lo as u32;
  84. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  85. v |= ((self.itable_unused_hi as u64) << 32) as u32;
  86. }
  87. v
  88. }
  89. pub fn get_used_dirs_count(&self, s: &Ext4Superblock) -> u32 {
  90. let mut v = self.used_dirs_count_lo as u32;
  91. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  92. v |= ((self.used_dirs_count_hi as u64) << 32) as u32;
  93. }
  94. v
  95. }
  96. pub fn set_used_dirs_count(&mut self, s: &Ext4Superblock, cnt: u32) {
  97. self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
  98. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  99. self.itable_unused_hi = (cnt >> 16) as u16;
  100. }
  101. }
  102. pub fn set_itable_unused(&mut self, s: &Ext4Superblock, cnt: u32) {
  103. self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
  104. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  105. self.itable_unused_hi = (cnt >> 16) as u16;
  106. }
  107. }
  108. pub fn set_free_inodes_count(&mut self, s: &Ext4Superblock, cnt: u32) {
  109. self.free_inodes_count_lo = ((cnt << 16) >> 16) as u16;
  110. if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  111. self.free_inodes_count_hi = (cnt >> 16) as u16;
  112. }
  113. }
  114. pub fn free_inodes_count(&self) -> u32 {
  115. ((self.free_inodes_count_hi as u32) << 16) | self.free_inodes_count_lo as u32
  116. }
  117. pub fn inode_table_first_block(&self) -> u64 {
  118. ((self.inode_table_first_block_hi as u64) << 32) | self.inode_table_first_block_lo as u64
  119. }
  120. pub fn sync_to_disk(
  121. &self,
  122. block_device: Arc<dyn BlockDevice>,
  123. bgid: usize,
  124. super_block: &Ext4Superblock,
  125. ) {
  126. let dsc_cnt = BLOCK_SIZE / super_block.desc_size() as usize;
  127. // let dsc_per_block = dsc_cnt;
  128. let dsc_id = bgid / dsc_cnt;
  129. // let first_meta_bg = super_block.first_meta_bg;
  130. let first_data_block = super_block.first_data_block();
  131. let block_id = first_data_block as usize + dsc_id + 1;
  132. let offset = (bgid % dsc_cnt) * super_block.desc_size() as usize;
  133. let data = unsafe {
  134. core::slice::from_raw_parts(
  135. self as *const _ as *const u8,
  136. size_of::<Ext4BlockGroupDesc>(),
  137. )
  138. };
  139. block_device.write_offset(block_id * BLOCK_SIZE + offset, data);
  140. }
  141. pub fn calc_checksum(&mut self, bgid: u32, super_block: &Ext4Superblock) -> u16 {
  142. let desc_size = super_block.desc_size();
  143. let orig_checksum = self.checksum;
  144. // 准备:暂时将bg校验和设为0
  145. self.checksum = 0;
  146. // uuid checksum
  147. let mut checksum = ext4_crc32c(
  148. EXT4_CRC32_INIT,
  149. &super_block.uuid(),
  150. super_block.uuid().len() as u32,
  151. );
  152. // bgid checksum
  153. checksum = ext4_crc32c(checksum, &bgid.to_le_bytes(), 4);
  154. // cast self to &[u8]
  155. let self_bytes =
  156. unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, 0x40 as usize) };
  157. // bg checksum
  158. checksum = ext4_crc32c(checksum, self_bytes, desc_size as u32);
  159. self.checksum = orig_checksum;
  160. let crc = (checksum & 0xFFFF) as u16;
  161. crc
  162. }
  163. pub fn set_block_group_checksum(&mut self, bgid: u32, super_block: &Ext4Superblock) {
  164. let csum = self.calc_checksum(bgid, super_block);
  165. self.checksum = csum;
  166. }
  167. pub fn sync_to_disk_with_csum(
  168. &mut self,
  169. block_device: Arc<dyn BlockDevice>,
  170. bgid: usize,
  171. super_block: &Ext4Superblock,
  172. ) {
  173. self.set_block_group_checksum(bgid as u32, super_block);
  174. self.sync_to_disk(block_device, bgid, super_block)
  175. }
  176. pub fn set_inode_bitmap_csum(&mut self, s: &Ext4Superblock, bitmap: &Bitmap) {
  177. let desc_size = s.desc_size();
  178. let csum = Self::calc_inode_bitmap_csum(&bitmap, s);
  179. let lo_csum = (csum & 0xFFFF).to_le();
  180. let hi_csum = (csum >> 16).to_le();
  181. if (s.features_read_only() & 0x400) >> 10 == 0 {
  182. return;
  183. }
  184. self.inode_bitmap_csum_lo = lo_csum as u16;
  185. if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
  186. self.inode_bitmap_csum_hi = hi_csum as u16;
  187. }
  188. }
  189. pub fn set_block_bitmap_csum(&mut self, s: &Ext4Superblock, bitmap: &Bitmap) {
  190. let desc_size = s.desc_size();
  191. let csum = Self::calc_block_bitmap_csum(&bitmap, s);
  192. let lo_csum = (csum & 0xFFFF).to_le();
  193. let hi_csum = (csum >> 16).to_le();
  194. if (s.features_read_only() & 0x400) >> 10 == 0 {
  195. return;
  196. }
  197. self.block_bitmap_csum_lo = lo_csum as u16;
  198. if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
  199. self.block_bitmap_csum_hi = hi_csum as u16;
  200. }
  201. }
  202. pub fn get_free_blocks_count(&self) -> u64 {
  203. let mut v = self.free_blocks_count_lo as u64;
  204. if self.free_blocks_count_hi != 0 {
  205. v |= (self.free_blocks_count_hi as u64) << 32;
  206. }
  207. v
  208. }
  209. pub fn set_free_blocks_count(&mut self, cnt: u64) {
  210. self.free_blocks_count_lo = ((cnt << 32) >> 32) as u16;
  211. self.free_blocks_count_hi = (cnt >> 32) as u16;
  212. }
  213. pub fn calc_inode_bitmap_csum(bitmap: &Bitmap, s: &Ext4Superblock) -> u32 {
  214. let inodes_per_group = s.inodes_per_group();
  215. let uuid = s.uuid();
  216. let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
  217. csum = ext4_crc32c(csum, bitmap.as_raw(), (inodes_per_group + 7) / 8);
  218. csum
  219. }
  220. pub fn calc_block_bitmap_csum(bitmap: &Bitmap, s: &Ext4Superblock) -> u32 {
  221. let blocks_per_group = s.blocks_per_group();
  222. let uuid = s.uuid();
  223. let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
  224. csum = ext4_crc32c(csum, bitmap.as_raw(), (blocks_per_group / 8) as u32);
  225. csum
  226. }
  227. }