123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- //!# The Defination of Ext4 Block Group Description
- //!
- //! Block Group Descriptor is the second field of Ext4 Block Group.
- //!
- //! | Super Block | Group Descriptor | Reserved GDT Blocks |
- //! | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
- //!
- //! See [`super`] for more information.
- use super::crc::*;
- use super::Bitmap;
- use super::BlockDevice;
- use super::Ext4Superblock;
- use crate::constants::*;
- use crate::prelude::*;
- #[derive(Debug, Default, Clone, Copy)]
- #[repr(C, packed)]
- pub struct Ext4BlockGroupDesc {
- block_bitmap_lo: u32, // 块位图块
- inode_bitmap_lo: u32, // 节点位图块
- inode_table_first_block_lo: u32, // 节点表块
- free_blocks_count_lo: u16, // 空闲块数
- free_inodes_count_lo: u16, // 空闲节点数
- used_dirs_count_lo: u16, // 目录数
- flags: u16, // EXT4_BG_flags (INODE_UNINIT, etc)
- exclude_bitmap_lo: u32, // 快照排除位图
- block_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+bbitmap) LE
- inode_bitmap_csum_lo: u16, // crc32c(s_uuid+grp_num+ibitmap) LE
- itable_unused_lo: u16, // 未使用的节点数
- checksum: u16, // crc16(sb_uuid+group+desc)
- block_bitmap_hi: u32, // 块位图块 MSB
- inode_bitmap_hi: u32, // 节点位图块 MSB
- inode_table_first_block_hi: u32, // 节点表块 MSB
- free_blocks_count_hi: u16, // 空闲块数 MSB
- free_inodes_count_hi: u16, // 空闲节点数 MSB
- used_dirs_count_hi: u16, // 目录数 MSB
- itable_unused_hi: u16, // 未使用的节点数 MSB
- exclude_bitmap_hi: u32, // 快照排除位图 MSB
- block_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+bbitmap) BE
- inode_bitmap_csum_hi: u16, // crc32c(s_uuid+grp_num+ibitmap) BE
- reserved: u32, // 填充
- }
- impl TryFrom<&[u8]> for Ext4BlockGroupDesc {
- type Error = u64;
- fn try_from(data: &[u8]) -> core::result::Result<Self, u64> {
- let data = &data[..size_of::<Ext4BlockGroupDesc>()];
- Ok(unsafe { core::ptr::read(data.as_ptr() as *const _) })
- }
- }
- impl Ext4BlockGroupDesc {
- pub fn load(
- block_device: Arc<dyn BlockDevice>,
- super_block: &Ext4Superblock,
- block_group_id: usize,
- ) -> core::result::Result<Self, u64> {
- let dsc_cnt = BLOCK_SIZE / super_block.desc_size() as usize;
- let dsc_id = block_group_id / dsc_cnt;
- let first_data_block = super_block.first_data_block();
- let block_id = first_data_block as usize + dsc_id + 1;
- let offset = (block_group_id % dsc_cnt) * super_block.desc_size() as usize;
- let data = block_device.read_offset(block_id * BLOCK_SIZE);
- let block_group_data =
- &data[offset as usize..offset as usize + size_of::<Ext4BlockGroupDesc>()];
- let bg = Ext4BlockGroupDesc::try_from(block_group_data);
- bg
- }
- pub fn get_block_bitmap_block(&self, s: &Ext4Superblock) -> u64 {
- let mut v = self.block_bitmap_lo as u64;
- let desc_size = s.desc_size();
- if desc_size > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- v |= (self.block_bitmap_hi as u64) << 32;
- }
- v
- }
- pub fn get_inode_bitmap_block(&self, s: &Ext4Superblock) -> u64 {
- let mut v = self.inode_bitmap_lo as u64;
- let desc_size = s.desc_size();
- if desc_size > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- v |= (self.inode_bitmap_hi as u64) << 32;
- }
- v
- }
- pub fn get_itable_unused(&mut self, s: &Ext4Superblock) -> u32 {
- let mut v = self.itable_unused_lo as u32;
- if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- v |= ((self.itable_unused_hi as u64) << 32) as u32;
- }
- v
- }
- pub fn get_used_dirs_count(&self, s: &Ext4Superblock) -> u32 {
- let mut v = self.used_dirs_count_lo as u32;
- if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- v |= ((self.used_dirs_count_hi as u64) << 32) as u32;
- }
- v
- }
- pub fn set_used_dirs_count(&mut self, s: &Ext4Superblock, cnt: u32) {
- self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
- if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- self.itable_unused_hi = (cnt >> 16) as u16;
- }
- }
- pub fn set_itable_unused(&mut self, s: &Ext4Superblock, cnt: u32) {
- self.itable_unused_lo = ((cnt << 16) >> 16) as u16;
- if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- self.itable_unused_hi = (cnt >> 16) as u16;
- }
- }
- pub fn set_free_inodes_count(&mut self, s: &Ext4Superblock, cnt: u32) {
- self.free_inodes_count_lo = ((cnt << 16) >> 16) as u16;
- if s.desc_size() > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE {
- self.free_inodes_count_hi = (cnt >> 16) as u16;
- }
- }
- pub fn free_inodes_count(&self) -> u32 {
- ((self.free_inodes_count_hi as u32) << 16) | self.free_inodes_count_lo as u32
- }
- pub fn inode_table_first_block(&self) -> u64 {
- ((self.inode_table_first_block_hi as u64) << 32) | self.inode_table_first_block_lo as u64
- }
- pub fn sync_to_disk(
- &self,
- block_device: Arc<dyn BlockDevice>,
- bgid: usize,
- super_block: &Ext4Superblock,
- ) {
- let dsc_cnt = BLOCK_SIZE / super_block.desc_size() as usize;
- // let dsc_per_block = dsc_cnt;
- let dsc_id = bgid / dsc_cnt;
- // let first_meta_bg = super_block.first_meta_bg;
- let first_data_block = super_block.first_data_block();
- let block_id = first_data_block as usize + dsc_id + 1;
- let offset = (bgid % dsc_cnt) * super_block.desc_size() as usize;
- let data = unsafe {
- core::slice::from_raw_parts(
- self as *const _ as *const u8,
- size_of::<Ext4BlockGroupDesc>(),
- )
- };
- block_device.write_offset(block_id * BLOCK_SIZE + offset, data);
- }
- pub fn calc_checksum(&mut self, bgid: u32, super_block: &Ext4Superblock) -> u16 {
- let desc_size = super_block.desc_size();
- let orig_checksum = self.checksum;
- // 准备:暂时将bg校验和设为0
- self.checksum = 0;
- // uuid checksum
- let mut checksum = ext4_crc32c(
- EXT4_CRC32_INIT,
- &super_block.uuid(),
- super_block.uuid().len() as u32,
- );
- // bgid checksum
- checksum = ext4_crc32c(checksum, &bgid.to_le_bytes(), 4);
- // cast self to &[u8]
- let self_bytes =
- unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, 0x40 as usize) };
- // bg checksum
- checksum = ext4_crc32c(checksum, self_bytes, desc_size as u32);
- self.checksum = orig_checksum;
- let crc = (checksum & 0xFFFF) as u16;
- crc
- }
- pub fn set_block_group_checksum(&mut self, bgid: u32, super_block: &Ext4Superblock) {
- let csum = self.calc_checksum(bgid, super_block);
- self.checksum = csum;
- }
- pub fn sync_to_disk_with_csum(
- &mut self,
- block_device: Arc<dyn BlockDevice>,
- bgid: usize,
- super_block: &Ext4Superblock,
- ) {
- self.set_block_group_checksum(bgid as u32, super_block);
- self.sync_to_disk(block_device, bgid, super_block)
- }
- pub fn set_inode_bitmap_csum(&mut self, s: &Ext4Superblock, bitmap: &Bitmap) {
- let desc_size = s.desc_size();
- let csum = Self::calc_inode_bitmap_csum(&bitmap, s);
- let lo_csum = (csum & 0xFFFF).to_le();
- let hi_csum = (csum >> 16).to_le();
- if (s.features_read_only() & 0x400) >> 10 == 0 {
- return;
- }
- self.inode_bitmap_csum_lo = lo_csum as u16;
- if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
- self.inode_bitmap_csum_hi = hi_csum as u16;
- }
- }
- pub fn set_block_bitmap_csum(&mut self, s: &Ext4Superblock, bitmap: &Bitmap) {
- let desc_size = s.desc_size();
- let csum = Self::calc_block_bitmap_csum(&bitmap, s);
- let lo_csum = (csum & 0xFFFF).to_le();
- let hi_csum = (csum >> 16).to_le();
- if (s.features_read_only() & 0x400) >> 10 == 0 {
- return;
- }
- self.block_bitmap_csum_lo = lo_csum as u16;
- if desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE {
- self.block_bitmap_csum_hi = hi_csum as u16;
- }
- }
- pub fn get_free_blocks_count(&self) -> u64 {
- let mut v = self.free_blocks_count_lo as u64;
- if self.free_blocks_count_hi != 0 {
- v |= (self.free_blocks_count_hi as u64) << 32;
- }
- v
- }
- pub fn set_free_blocks_count(&mut self, cnt: u64) {
- self.free_blocks_count_lo = ((cnt << 32) >> 32) as u16;
- self.free_blocks_count_hi = (cnt >> 32) as u16;
- }
- pub fn calc_inode_bitmap_csum(bitmap: &Bitmap, s: &Ext4Superblock) -> u32 {
- let inodes_per_group = s.inodes_per_group();
- let uuid = s.uuid();
- let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
- csum = ext4_crc32c(csum, bitmap.as_raw(), (inodes_per_group + 7) / 8);
- csum
- }
- pub fn calc_block_bitmap_csum(bitmap: &Bitmap, s: &Ext4Superblock) -> u32 {
- let blocks_per_group = s.blocks_per_group();
- let uuid = s.uuid();
- let mut csum = ext4_crc32c(EXT4_CRC32_INIT, &uuid, uuid.len() as u32);
- csum = ext4_crc32c(csum, bitmap.as_raw(), (blocks_per_group / 8) as u32);
- csum
- }
- }
|