ref: e686e6cd460cc1767c1a6dcf19841d1d0df4bb7b
parent: 10dd1d4f9b5097a5b96523093caeb97181d78c76
author: ngkaho1234 <[email protected]>
date: Wed Oct 28 09:54:37 EDT 2015
METADATA_CSUM: inode and block group descriptor checksum verification added
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -489,76 +489,6 @@
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 @@
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 @@
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)
{
@@ -751,6 +785,13 @@
ref->index = index + 1;
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;
}