Browse Source

METADATA_CSUM: inode and block group descriptor checksum verification added

pull/11/head
ngkaho1234 9 years ago
parent
commit
e686e6cd46
  1. 181
      lwext4/ext4_fs.c

181
lwext4/ext4_fs.c

@ -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;
}

Loading…
Cancel
Save