|
|
@ -489,76 +489,6 @@ static ext4_fsblk_t ext4_fs_get_descriptor_block(struct ext4_sblock *s, |
|
|
|
return (has_super + ext4_fs_first_bg_block_no(s, bgid)); |
|
|
|
} |
|
|
|
|
|
|
|
int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid, |
|
|
|
struct ext4_block_group_ref *ref) |
|
|
|
{ |
|
|
|
/* Compute number of descriptors, that fits in one data block */ |
|
|
|
uint32_t dsc_per_block = |
|
|
|
ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb); |
|
|
|
|
|
|
|
/* Block group descriptor table starts at the next block after
|
|
|
|
* superblock */ |
|
|
|
uint64_t block_id = |
|
|
|
ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block); |
|
|
|
|
|
|
|
uint32_t offset = |
|
|
|
(bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb); |
|
|
|
|
|
|
|
int rc = ext4_block_get(fs->bdev, &ref->block, block_id); |
|
|
|
if (rc != EOK) |
|
|
|
return rc; |
|
|
|
|
|
|
|
ref->block_group = (void *)(ref->block.data + offset); |
|
|
|
ref->fs = fs; |
|
|
|
ref->index = bgid; |
|
|
|
ref->dirty = false; |
|
|
|
|
|
|
|
if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) { |
|
|
|
rc = ext4_fs_init_block_bitmap(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
ext4_bg_clear_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_BLOCK_UNINIT); |
|
|
|
|
|
|
|
ref->dirty = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) { |
|
|
|
rc = ext4_fs_init_inode_bitmap(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(ref->fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
|
|
|
|
ext4_bg_clear_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_INODE_UNINIT); |
|
|
|
|
|
|
|
if (!ext4_bg_has_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_ITABLE_ZEROED)) { |
|
|
|
rc = ext4_fs_init_inode_table(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
|
|
|
|
ext4_bg_set_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_ITABLE_ZEROED); |
|
|
|
} |
|
|
|
|
|
|
|
ref->dirty = true; |
|
|
|
} |
|
|
|
|
|
|
|
return EOK; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* BIG FAT NOTES: |
|
|
|
* Currently we do not verify the checksum of block_group_desc |
|
|
|
* and inode. |
|
|
|
*/ |
|
|
|
|
|
|
|
/**@brief Compute checksum of block group descriptor.
|
|
|
|
* @param sb Superblock |
|
|
|
* @param bgid Index of block group in the filesystem |
|
|
@ -629,6 +559,96 @@ static uint16_t ext4_fs_bg_checksum(struct ext4_sblock *sb, uint32_t bgid, |
|
|
|
return crc; |
|
|
|
} |
|
|
|
|
|
|
|
#if CONFIG_META_CSUM_ENABLE |
|
|
|
static bool ext4_fs_verify_bg_csum(struct ext4_sblock *sb, |
|
|
|
uint32_t bgid, |
|
|
|
struct ext4_bgroup *bg) |
|
|
|
{ |
|
|
|
if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) |
|
|
|
return true; |
|
|
|
|
|
|
|
return ext4_fs_bg_checksum(sb, |
|
|
|
bgid, |
|
|
|
bg) == |
|
|
|
to_le16(bg->checksum); |
|
|
|
} |
|
|
|
#else |
|
|
|
#define ext4_fs_verify_bg_csum(...) true |
|
|
|
#endif |
|
|
|
|
|
|
|
int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid, |
|
|
|
struct ext4_block_group_ref *ref) |
|
|
|
{ |
|
|
|
/* Compute number of descriptors, that fits in one data block */ |
|
|
|
uint32_t dsc_per_block = |
|
|
|
ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb); |
|
|
|
|
|
|
|
/* Block group descriptor table starts at the next block after
|
|
|
|
* superblock */ |
|
|
|
uint64_t block_id = |
|
|
|
ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block); |
|
|
|
|
|
|
|
uint32_t offset = |
|
|
|
(bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb); |
|
|
|
|
|
|
|
int rc = ext4_block_get(fs->bdev, &ref->block, block_id); |
|
|
|
if (rc != EOK) |
|
|
|
return rc; |
|
|
|
|
|
|
|
ref->block_group = (void *)(ref->block.data + offset); |
|
|
|
ref->fs = fs; |
|
|
|
ref->index = bgid; |
|
|
|
ref->dirty = false; |
|
|
|
|
|
|
|
if (!ext4_fs_verify_bg_csum(&fs->sb, |
|
|
|
bgid, |
|
|
|
ref->block_group)) { |
|
|
|
ext4_dbg(DEBUG_FS, |
|
|
|
DBG_WARN "Block group descriptor checksum failed." |
|
|
|
"Block group index: %" PRIu32"\n", |
|
|
|
bgid); |
|
|
|
} |
|
|
|
|
|
|
|
if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) { |
|
|
|
rc = ext4_fs_init_block_bitmap(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
ext4_bg_clear_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_BLOCK_UNINIT); |
|
|
|
|
|
|
|
ref->dirty = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) { |
|
|
|
rc = ext4_fs_init_inode_bitmap(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(ref->fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
|
|
|
|
ext4_bg_clear_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_INODE_UNINIT); |
|
|
|
|
|
|
|
if (!ext4_bg_has_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_ITABLE_ZEROED)) { |
|
|
|
rc = ext4_fs_init_inode_table(ref); |
|
|
|
if (rc != EOK) { |
|
|
|
ext4_block_set(fs->bdev, &ref->block); |
|
|
|
return rc; |
|
|
|
} |
|
|
|
|
|
|
|
ext4_bg_set_flag(ref->block_group, |
|
|
|
EXT4_BLOCK_GROUP_ITABLE_ZEROED); |
|
|
|
} |
|
|
|
|
|
|
|
ref->dirty = true; |
|
|
|
} |
|
|
|
|
|
|
|
return EOK; |
|
|
|
} |
|
|
|
|
|
|
|
int ext4_fs_put_block_group_ref(struct ext4_block_group_ref *ref) |
|
|
|
{ |
|
|
|
/* Check if reference modified */ |
|
|
@ -697,6 +717,20 @@ static void ext4_fs_set_inode_checksum(struct ext4_inode_ref *inode_ref) |
|
|
|
ext4_fs_inode_checksum(inode_ref)); |
|
|
|
} |
|
|
|
|
|
|
|
#if CONFIG_META_CSUM_ENABLE |
|
|
|
static bool ext4_fs_verify_inode_csum(struct ext4_inode_ref *inode_ref) |
|
|
|
{ |
|
|
|
struct ext4_sblock *sb = &inode_ref->fs->sb; |
|
|
|
if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) |
|
|
|
return true; |
|
|
|
|
|
|
|
return ext4_inode_get_checksum(sb, inode_ref->inode) == |
|
|
|
ext4_fs_inode_checksum(inode_ref); |
|
|
|
} |
|
|
|
#else |
|
|
|
#define ext4_fs_verify_inode_csum(...) true |
|
|
|
#endif |
|
|
|
|
|
|
|
int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index, |
|
|
|
struct ext4_inode_ref *ref) |
|
|
|
{ |
|
|
@ -752,6 +786,13 @@ int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index, |
|
|
|
ref->fs = fs; |
|
|
|
ref->dirty = false; |
|
|
|
|
|
|
|
if (!ext4_fs_verify_inode_csum(ref)) { |
|
|
|
ext4_dbg(DEBUG_FS, |
|
|
|
DBG_WARN "Inode checksum failed." |
|
|
|
"Inode: %" PRIu32"\n", |
|
|
|
ref->index); |
|
|
|
} |
|
|
|
|
|
|
|
return EOK; |
|
|
|
} |
|
|
|
|
|
|
|