super_block.rs 9.2 KB

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