uint32_t ext4_num_base_meta_clusters(struct ext4_sblock *s, uint32_t block_group) { uint32_t num; uint32_t dsc_per_block = ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s); num = ext4_sb_is_super_in_bg(s, block_group); if (!ext4_sb_feature_incom(s, EXT4_FINCOM_META_BG) || block_group < ext4_sb_first_meta_bg(s) * dsc_per_block) { if (num) { num += ext4_bg_num_gdb(s, block_group); num += ext4_get16(s, s_reserved_gdt_blocks); } } else { num += ext4_bg_num_gdb(s, block_group); } uint32_t clustersize = 1024 << ext4_get32(s, log_cluster_size); uint32_t cluster_ratio = clustersize / ext4_sb_get_block_size(s); uint32_t v = (num + cluster_ratio - 1) >> ext4_get32(s, log_cluster_size); return v; }
bool ext4_sb_check(struct ext4_sblock *s) { if (ext4_get16(s, magic) != EXT4_SUPERBLOCK_MAGIC) return false; if (ext4_get32(s, inodes_count) == 0) return false; if (ext4_sb_get_blocks_cnt(s) == 0) return false; if (ext4_get32(s, blocks_per_group) == 0) return false; if (ext4_get32(s, inodes_per_group) == 0) return false; if (ext4_get16(s, inode_size) < 128) return false; if (ext4_get32(s, first_inode) < 11) return false; if (ext4_sb_get_desc_size(s) < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE) return false; if (ext4_sb_get_desc_size(s) > EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE) return false; if (!ext4_sb_verify_csum(s)) return false; return true; }
/**@brief Compute number of block group from block address. * @param sb superblock pointer. * @param baddr Absolute address of block. * @return Block group index */ uint32_t ext4_balloc_get_bgid_of_block(struct ext4_sblock *s, uint64_t baddr) { if (ext4_get32(s, first_data_block) && baddr) baddr--; return baddr / ext4_get32(s, blocks_per_group); }
/**@brief Compute the starting block address of a block group * @param sb superblock pointer. * @param bgid block group index * @return Block address */ uint64_t ext4_balloc_get_block_of_bgid(struct ext4_sblock *s, uint32_t bgid) { uint64_t baddr = 0; if (ext4_get32(s, first_data_block)) baddr++; baddr += bgid * ext4_get32(s, blocks_per_group); return baddr; }
uint32_t ext4_inodes_in_group_cnt(struct ext4_sblock *s, uint32_t bgid) { uint32_t block_group_count = ext4_block_group_cnt(s); uint32_t inodes_per_group = ext4_get32(s, inodes_per_group); uint32_t total_inodes = ext4_get32(s, inodes_count); if (bgid < block_group_count - 1) return inodes_per_group; return (total_inodes - ((block_group_count - 1) * inodes_per_group)); }
uint32_t ext4_blocks_in_group_cnt(struct ext4_sblock *s, uint32_t bgid) { uint32_t block_group_count = ext4_block_group_cnt(s); uint32_t blocks_per_group = ext4_get32(s, blocks_per_group); uint64_t total_blocks = ext4_sb_get_blocks_cnt(s); if (bgid < block_group_count - 1) return blocks_per_group; return (uint32_t)(total_blocks - ((block_group_count - 1) * blocks_per_group)); }
uint32_t ext4_block_group_cnt(struct ext4_sblock *s) { uint64_t blocks_count = ext4_sb_get_blocks_cnt(s); uint32_t blocks_per_group = ext4_get32(s, blocks_per_group); uint32_t block_groups_count = (uint32_t)(blocks_count / blocks_per_group); if (blocks_count % blocks_per_group) block_groups_count++; return block_groups_count; }
static uint32_t ext4_balloc_bitmap_csum(struct ext4_sblock *sb, void *bitmap) { uint32_t checksum = 0; if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) { uint32_t blocks_per_group = ext4_get32(sb, blocks_per_group); /* First calculate crc32 checksum against fs uuid */ checksum = ext4_crc32c(EXT4_CRC32_INIT, sb->uuid, sizeof(sb->uuid)); /* Then calculate crc32 checksum against block_group_desc */ checksum = ext4_crc32c(checksum, bitmap, blocks_per_group / 8); } return checksum; }