ref: 76ccc5426eab8185b7e0bf43a35ebb7bcedda79c
parent: 1de45d8f0584b97a29b7e2655998891877eba6c6
author: ngkaho1234 <[email protected]>
date: Sat Oct 24 17:08:49 EDT 2015
METADATA_CSUM: inode added.
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -546,6 +546,12 @@
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
@@ -633,10 +639,53 @@
return ext4_block_set(ref->fs->bdev, &ref->block);
}
-/*
- * BIG FAT NOTES:
- * Currently we do not verify the checksum of block_group_desc.
- */
+static uint32_t ext4_fs_inode_checksum(struct ext4_inode_ref *inode_ref)
+{
+ uint32_t checksum = 0;
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ uint16_t inode_size = ext4_get16(sb, inode_size);
+
+ if (ext4_sb_has_feature_read_only(sb,
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+ uint32_t orig_checksum;
+
+ uint32_t ino_index = to_le32(inode_ref->index);
+ uint32_t ino_gen =
+ to_le32(ext4_inode_get_generation(inode_ref->inode));
+
+ /* Preparation: temporarily set bg checksum to 0 */
+ orig_checksum = ext4_inode_get_checksum(sb, inode_ref->inode);
+ ext4_inode_set_checksum(sb, inode_ref->inode, 0);
+
+ /* First calculate crc32 checksum against fs uuid */
+ checksum = ext4_crc32c(~0, sb->uuid, sizeof(sb->uuid));
+ /* Then calculate crc32 checksum against inode number
+ * and inode generation */
+ checksum = ext4_crc32c(checksum, &ino_index,
+ sizeof(ino_index));
+ checksum = ext4_crc32c(checksum, &ino_gen,
+ sizeof(ino_gen));
+ /* Finally calculate crc32 checksum against
+ * the entire inode */
+ checksum = ext4_crc32c(checksum, inode_ref->inode,
+ inode_size);
+ ext4_inode_set_checksum(sb, inode_ref->inode,
+ orig_checksum);
+ }
+ return checksum;
+}
+
+static void ext4_fs_set_inode_checksum(struct ext4_inode_ref *inode_ref)
+{
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ if (!ext4_sb_has_feature_read_only(sb,
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ return;
+
+ ext4_inode_set_checksum(sb, inode_ref->inode,
+ ext4_fs_inode_checksum(inode_ref));
+}
+
int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index,
struct ext4_inode_ref *ref)
{
@@ -700,6 +749,7 @@
/* Check if reference modified */
if (ref->dirty) {
/* Mark block dirty for writing changes to physical device */
+ ext4_fs_set_inode_checksum(ref);
ref->block.dirty = true;
}
--- a/lwext4/ext4_inode.c
+++ b/lwext4/ext4_inode.c
@@ -108,6 +108,31 @@
inode->size_hi = to_le32(size >> 32);
}
+uint32_t
+ext4_inode_get_checksum(struct ext4_sblock *sb, struct ext4_inode *inode)
+{
+ uint16_t inode_size = ext4_get16(sb, inode_size);
+ uint32_t v = to_le16(inode->osd2.linux2.checksum_lo);
+
+ if (inode_size > EXT4_GOOD_OLD_INODE_SIZE)
+ v |= ((uint32_t)to_le16(inode->checksum_hi)) << 16;
+
+ return v;
+}
+
+void
+ext4_inode_set_checksum(struct ext4_sblock *sb, struct ext4_inode *inode,
+ uint32_t checksum)
+{
+ uint16_t inode_size = ext4_get16(sb, inode_size);
+ inode->osd2.linux2.checksum_lo =
+ to_le16((checksum << 16) >> 16);
+
+ if (inode_size > EXT4_GOOD_OLD_INODE_SIZE)
+ inode->checksum_hi = to_le16(checksum >> 16);
+
+}
+
uint32_t ext4_inode_get_access_time(struct ext4_inode *inode)
{
return to_le32(inode->access_time);
--- a/lwext4/ext4_inode.h
+++ b/lwext4/ext4_inode.h
@@ -280,6 +280,21 @@
*/
void ext4_inode_set_flag(struct ext4_inode *inode, uint32_t f);
+/**@brief Get inode checksum(crc32)
+ * @param sb Superblock
+ * @param inode I-node to get checksum value from
+ */
+uint32_t
+ext4_inode_get_checksum(struct ext4_sblock *sb, struct ext4_inode *inode);
+
+/**@brief Get inode checksum(crc32)
+ * @param sb Superblock
+ * @param inode I-node to get checksum value from
+ */
+void
+ext4_inode_set_checksum(struct ext4_sblock *sb, struct ext4_inode *inode,
+ uint32_t checksum);
+
/**@brief Check if i-node can be truncated.
* @param sb Superblock
* @param inode I-node to check
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -393,7 +393,8 @@
uint16_t file_acl_high;
uint16_t uid_high;
uint16_t gid_high;
- uint32_t reserved2;
+ uint16_t checksum_lo; /* crc32c(uuid+inum+inode) LE */
+ uint16_t reserved2;
} linux2;
struct {
uint16_t reserved1;
@@ -405,7 +406,7 @@
} __attribute__((packed)) osd2;
uint16_t extra_isize;
- uint16_t pad1;
+ uint16_t checksum_hi; /* crc32c(uuid+inum+inode) BE */
uint32_t ctime_extra; /* Extra change time (nsec << 2 | epoch) */
uint32_t mtime_extra; /* Extra Modification time (nsec << 2 | epoch) */
uint32_t atime_extra; /* Extra Access time (nsec << 2 | epoch) */