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; }
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; }
uint32_t ext4_bg_num_gdb(struct ext4_sblock *s, uint32_t group) { uint32_t dsc_per_block = ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s); uint32_t first_meta_bg = ext4_sb_first_meta_bg(s); uint32_t metagroup = group / dsc_per_block; if (!ext4_sb_feature_incom(s,EXT4_FINCOM_META_BG) || metagroup < first_meta_bg) return ext4_bg_num_gdb_nometa(s, group); return ext4_bg_num_gdb_meta(s, group); }
static uint32_t ext4_bg_num_gdb_meta(struct ext4_sblock *s, uint32_t group) { uint32_t dsc_per_block = ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s); uint32_t metagroup = group / dsc_per_block; uint32_t first = metagroup * dsc_per_block; uint32_t last = first + dsc_per_block - 1; if (group == first || group == first + 1 || group == last) return 1; return 0; }
static uint32_t ext4_bg_num_gdb_nometa(struct ext4_sblock *s, uint32_t group) { if (!ext4_sb_is_super_in_bg(s, group)) return 0; uint32_t dsc_per_block = ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s); uint32_t db_count = (ext4_block_group_cnt(s) + dsc_per_block - 1) / dsc_per_block; if (ext4_sb_feature_incom(s, EXT4_FINCOM_META_BG)) return ext4_sb_first_meta_bg(s); return db_count; }
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; } #else #define ext4_balloc_bitmap_csum(...) 0 #endif void ext4_balloc_set_bitmap_csum(struct ext4_sblock *sb, struct ext4_bgroup *bg, void *bitmap __unused) { int desc_size = ext4_sb_get_desc_size(sb); uint32_t checksum = ext4_balloc_bitmap_csum(sb, bitmap); uint16_t lo_checksum = to_le16(checksum & 0xFFFF), hi_checksum = to_le16(checksum >> 16); if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) return; /* See if we need to assign a 32bit checksum */ bg->block_bitmap_csum_lo = lo_checksum; if (desc_size == EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE) bg->block_bitmap_csum_hi = hi_checksum; } #if CONFIG_META_CSUM_ENABLE