super_block.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. use crate::constants::*;
  2. use crate::prelude::*;
  3. use super::BlockDevice;
  4. use super::Ext4Inode;
  5. // 结构体表示超级块
  6. #[repr(C)]
  7. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  8. pub struct Ext4Superblock {
  9. inodes_count: u32, // 节点数
  10. blocks_count_lo: u32, // 块数
  11. reserved_blocks_count_lo: u32, // 保留块数
  12. free_blocks_count_lo: u32, // 空闲块数
  13. free_inodes_count: u32, // 空闲节点数
  14. first_data_block: u32, // 第一个数据块
  15. log_block_size: u32, // 块大小
  16. log_cluster_size: u32, // 废弃的片段大小
  17. blocks_per_group: u32, // 每组块数
  18. frags_per_group: u32, // 废弃的每组片段数
  19. inodes_per_group: u32, // 每组节点数
  20. mount_time: u32, // 挂载时间
  21. write_time: u32, // 写入时间
  22. mount_count: u16, // 挂载次数
  23. max_mount_count: u16, // 最大挂载次数
  24. magic: u16, // 魔数,0xEF53
  25. state: u16, // 文件系统状态
  26. errors: u16, // 检测到错误时的行为
  27. minor_rev_level: u16, // 次版本号
  28. last_check_time: u32, // 最后检查时间
  29. check_interval: u32, // 检查间隔
  30. creator_os: u32, // 创建者操作系统
  31. rev_level: u32, // 版本号
  32. def_resuid: u16, // 保留块的默认uid
  33. def_resgid: u16, // 保留块的默认gid
  34. // 仅适用于EXT4_DYNAMIC_REV超级块的字段
  35. first_inode: u32, // 第一个非保留节点
  36. inode_size: u16, // 节点结构的大小
  37. block_group_index: u16, // 此超级块的块组索引
  38. features_compatible: u32, // 兼容特性集
  39. features_incompatible: u32, // 不兼容特性集
  40. features_read_only: u32, // 只读兼容特性集
  41. uuid: [u8; 16], // 卷的128位uuid
  42. volume_name: [u8; 16], // 卷名
  43. last_mounted: [u8; 64], // 最后挂载的目录
  44. algorithm_usage_bitmap: u32, // 用于压缩的算法
  45. // 性能提示。只有当EXT4_FEATURE_COMPAT_DIR_PREALLOC标志打开时,才进行目录预分配
  46. s_prealloc_blocks: u8, // 尝试预分配的块数
  47. s_prealloc_dir_blocks: u8, // 为目录预分配的块数
  48. s_reserved_gdt_blocks: u16, // 在线增长时每组保留的描述符数
  49. // 如果EXT4_FEATURE_COMPAT_HAS_JOURNAL设置,表示支持日志
  50. journal_uuid: [u8; 16], // 日志超级块的UUID
  51. journal_inode_number: u32, // 日志文件的节点号
  52. journal_dev: u32, // 日志文件的设备号
  53. last_orphan: u32, // 待删除节点的链表头
  54. hash_seed: [u32; 4], // HTREE散列种子
  55. default_hash_version: u8, // 默认的散列版本
  56. journal_backup_type: u8,
  57. desc_size: u16, // 组描述符的大小
  58. default_mount_opts: u32, // 默认的挂载选项
  59. first_meta_bg: u32, // 第一个元数据块组
  60. mkfs_time: u32, // 文件系统创建的时间
  61. journal_blocks: [u32; 17], // 日志节点的备份
  62. // 如果EXT4_FEATURE_COMPAT_64BIT设置,表示支持64位
  63. blocks_count_hi: u32, // 块数
  64. reserved_blocks_count_hi: u32, // 保留块数
  65. free_blocks_count_hi: u32, // 空闲块数
  66. min_extra_isize: u16, // 所有节点至少有#字节
  67. want_extra_isize: u16, // 新节点应该保留#字节
  68. flags: u32, // 杂项标志
  69. raid_stride: u16, // RAID步长
  70. mmp_interval: u16, // MMP检查的等待秒数
  71. mmp_block: u64, // 多重挂载保护的块
  72. raid_stripe_width: u32, // 所有数据磁盘上的块数(N * 步长)
  73. log_groups_per_flex: u8, // FLEX_BG组的大小
  74. checksum_type: u8,
  75. reserved_pad: u16,
  76. kbytes_written: u64, // 写入的千字节数
  77. snapshot_inum: u32, // 活动快照的节点号
  78. snapshot_id: u32, // 活动快照的顺序ID
  79. snapshot_r_blocks_count: u64, // 为活动快照的未来使用保留的块数
  80. snapshot_list: u32, // 磁盘上快照列表的头节点号
  81. error_count: u32, // 文件系统错误的数目
  82. first_error_time: u32, // 第一次发生错误的时间
  83. first_error_ino: u32, // 第一次发生错误的节点号
  84. first_error_block: u64, // 第一次发生错误的块号
  85. first_error_func: [u8; 32], // 第一次发生错误的函数
  86. first_error_line: u32, // 第一次发生错误的行号
  87. last_error_time: u32, // 最近一次发生错误的时间
  88. last_error_ino: u32, // 最近一次发生错误的节点号
  89. last_error_line: u32, // 最近一次发生错误的行号
  90. last_error_block: u64, // 最近一次发生错误的块号
  91. last_error_func: [u8; 32], // 最近一次发生错误的函数
  92. mount_opts: [u8; 64],
  93. usr_quota_inum: u32, // 用于跟踪用户配额的节点
  94. grp_quota_inum: u32, // 用于跟踪组配额的节点
  95. overhead_clusters: u32, // 文件系统中的开销块/簇
  96. backup_bgs: [u32; 2], // 有sparse_super2超级块的组
  97. encrypt_algos: [u8; 4], // 使用的加密算法
  98. encrypt_pw_salt: [u8; 16], // 用于string2key算法的盐
  99. lpf_ino: u32, // lost+found节点的位置
  100. padding: [u32; 100], // 块的末尾的填充
  101. checksum: u32, // crc32c(superblock)
  102. }
  103. impl TryFrom<Vec<u8>> for Ext4Superblock {
  104. type Error = u64;
  105. fn try_from(value: Vec<u8>) -> core::result::Result<Self, u64> {
  106. let data = &value[..size_of::<Ext4Superblock>()];
  107. Ok(unsafe { core::ptr::read(data.as_ptr() as *const _) })
  108. }
  109. }
  110. impl Ext4Superblock {
  111. /// Returns the size of inode structure.
  112. pub fn inode_size(&self) -> u16 {
  113. self.inode_size
  114. }
  115. /// Returns the size of inode structure.
  116. pub fn inode_size_file(&self, inode: &Ext4Inode) -> u64 {
  117. let mode = inode.mode;
  118. // 获取inode的低32位大小
  119. let mut v = inode.size as u64;
  120. // 如果文件系统的版本号大于0,并且inode的类型是文件
  121. if self.rev_level > 0 && (mode & EXT4_INODE_MODE_TYPE_MASK) == EXT4_INODE_MODE_FILE as u16 {
  122. // 获取inode的高32位大小,并左移32位
  123. let hi = (inode.size_hi as u64) << 32;
  124. // 用或运算符将低32位和高32位拼接为一个u64值
  125. v |= hi;
  126. }
  127. // 返回inode的大小
  128. v
  129. }
  130. pub fn uuid(&self) -> [u8; 16] {
  131. self.uuid
  132. }
  133. pub fn first_data_block(&self) -> u32 {
  134. self.first_data_block
  135. }
  136. pub fn free_inodes_count(&self) -> u32 {
  137. self.free_inodes_count
  138. }
  139. pub fn features_read_only(&self) -> u32 {
  140. self.features_read_only
  141. }
  142. /// Returns total number of inodes.
  143. pub fn total_inodes(&self) -> u32 {
  144. self.inodes_count
  145. }
  146. /// Returns the number of blocks in each block group.
  147. pub fn blocks_per_group(&self) -> u32 {
  148. self.blocks_per_group
  149. }
  150. /// Returns the size of block.
  151. pub fn block_size(&self) -> u32 {
  152. 1024 << self.log_block_size
  153. }
  154. /// Returns the number of inodes in each block group.
  155. pub fn inodes_per_group(&self) -> u32 {
  156. self.inodes_per_group
  157. }
  158. /// Returns the number of block groups.
  159. pub fn block_groups_count(&self) -> u32 {
  160. (((self.blocks_count_hi.to_le() as u64) << 32) as u32 | self.blocks_count_lo)
  161. / self.blocks_per_group
  162. }
  163. pub fn desc_size(&self) -> u16 {
  164. let size = self.desc_size;
  165. if size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
  166. return EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE as u16;
  167. } else {
  168. size
  169. }
  170. }
  171. pub fn extra_size(&self) -> u16 {
  172. self.want_extra_isize
  173. }
  174. pub fn get_inodes_in_group_cnt(&self, bgid: u32) -> u32 {
  175. let block_group_count = self.block_groups_count();
  176. let inodes_per_group = self.inodes_per_group;
  177. let total_inodes = ((self.inodes_count as u64) << 32) as u32;
  178. if bgid < block_group_count - 1 {
  179. inodes_per_group
  180. } else {
  181. total_inodes - ((block_group_count - 1) * inodes_per_group)
  182. }
  183. }
  184. pub fn decrease_free_inodes_count(&mut self) {
  185. self.free_inodes_count -= 1;
  186. }
  187. pub fn free_blocks_count(&self) -> u64 {
  188. self.free_blocks_count_lo as u64 | ((self.free_blocks_count_hi as u64) << 32).to_le()
  189. }
  190. pub fn set_free_blocks_count(&mut self, free_blocks: u64) {
  191. self.free_blocks_count_lo = ((free_blocks << 32) >> 32).to_le() as u32;
  192. self.free_blocks_count_hi = (free_blocks >> 32) as u32;
  193. }
  194. pub fn sync_to_disk(&self, block_device: Arc<dyn BlockDevice>) {
  195. let data = unsafe {
  196. core::slice::from_raw_parts(self as *const _ as *const u8, size_of::<Ext4Superblock>())
  197. };
  198. block_device.write_offset(BASE_OFFSET, data);
  199. }
  200. pub fn sync_to_disk_with_csum(&self, block_device: Arc<dyn BlockDevice>) {
  201. let data = unsafe {
  202. core::slice::from_raw_parts(self as *const _ as *const u8, size_of::<Ext4Superblock>())
  203. };
  204. block_device.write_offset(BASE_OFFSET, data);
  205. }
  206. pub fn sync_super_block_to_disk(&self, block_device: Arc<dyn BlockDevice>) {
  207. let data = unsafe {
  208. core::slice::from_raw_parts(self as *const _ as *const u8, size_of::<Ext4Superblock>())
  209. };
  210. block_device.write_offset(BASE_OFFSET, data);
  211. }
  212. }
  213. #[allow(unused)]
  214. pub fn ext4_inodes_in_group_cnt(bgid: u32, s: &Ext4Superblock) -> u32 {
  215. let block_group_count = s.block_groups_count();
  216. let inodes_per_group = s.inodes_per_group;
  217. let total_inodes = ((s.inodes_count as u64) << 32) as u32;
  218. if bgid < block_group_count - 1 {
  219. inodes_per_group
  220. } else {
  221. total_inodes - ((block_group_count - 1) * inodes_per_group)
  222. }
  223. }