shithub: lwext4

Download patch

ref: f925f21abdc2a3b49967ae8f38bdb1ba1d40dde2
parent: c8ca698ba9f650dda21b022918033a0c625b27c4
author: ngkaho1234 <[email protected]>
date: Fri Oct 23 18:25:06 EDT 2015

METADATA_CSUM: block & inode bitmap checksum added.

--- a/lwext4/ext4_balloc.c
+++ b/lwext4/ext4_balloc.c
@@ -42,6 +42,7 @@
 #include "ext4_config.h"
 #include "ext4_balloc.h"
 #include "ext4_super.h"
+#include "ext4_crc32c.h"
 #include "ext4_block_group.h"
 #include "ext4_fs.h"
 #include "ext4_bitmap.h"
@@ -77,6 +78,37 @@
 	return baddr;
 }
 
+static uint32_t ext4_balloc_bitmap_csum(struct ext4_sblock *sb,
+					void *bitmap)
+{
+	uint32_t checksum = 0;
+	if (ext4_sb_has_feature_read_only(sb,
+				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+		/* First calculate crc32 checksum against fs uuid */
+		checksum = ext4_crc32c(~0, sb->uuid, sizeof(sb->uuid));
+		/* Then calculate crc32 checksum against block_group_desc */
+		checksum = ext4_crc32c(checksum, bitmap,
+				     ext4_sb_get_block_size(sb));
+	}
+	return checksum;
+}
+
+static void ext4_balloc_set_bitmap_csum(struct ext4_sblock *sb,
+					struct ext4_bgroup *bg,
+					void *bitmap)
+{
+	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);
+	
+	/* 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;
+
+}
+
 int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, ext4_fsblk_t baddr)
 {
 	struct ext4_fs *fs = inode_ref->fs;
@@ -106,6 +138,8 @@
 	/* Modify bitmap */
 	ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
 	bitmap_block.dirty = true;
+	ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+				    bitmap_block.data);
 
 	/* Release block with bitmap */
 	rc = ext4_block_set(fs->bdev, &bitmap_block);
@@ -196,6 +230,8 @@
 		ext4_bmap_bits_free(bitmap_block.data, index_in_group_first,
 				    free_cnt);
 		bitmap_block.dirty = true;
+		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+					    bitmap_block.data);
 
 		count -= free_cnt;
 		first += free_cnt;
@@ -294,6 +330,8 @@
 	if (ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group)) {
 		ext4_bmap_bit_set(bitmap_block.data, index_in_group);
 		bitmap_block.dirty = true;
+		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+					    bitmap_block.data);
 		rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
 		if (rc != EOK) {
 			ext4_fs_put_block_group_ref(&bg_ref);
@@ -319,6 +357,8 @@
 			ext4_bmap_bit_set(bitmap_block.data, tmp_idx);
 
 			bitmap_block.dirty = true;
+			ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+						    bitmap_block.data);
 			rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
 			if (rc != EOK)
 				return rc;
@@ -336,6 +376,8 @@
 	if (rc == EOK) {
 		ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
 		bitmap_block.dirty = true;
+		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+					    bitmap_block.data);
 		rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
 		if (rc != EOK)
 			return rc;
@@ -409,6 +451,8 @@
 			ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
 
 			bitmap_block.dirty = true;
+			ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+						    bitmap_block.data);
 			rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
 			if (rc != EOK) {
 				ext4_fs_put_block_group_ref(&bg_ref);
@@ -508,6 +552,8 @@
 	if (*free) {
 		ext4_bmap_bit_set(bitmap_block.data, index_in_group);
 		bitmap_block.dirty = true;
+		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
+					    bitmap_block.data);
 	}
 
 	/* Release block with bitmap */
--- a/lwext4/ext4_ialloc.c
+++ b/lwext4/ext4_ialloc.c
@@ -43,6 +43,7 @@
 #include "ext4_types.h"
 #include "ext4_ialloc.h"
 #include "ext4_super.h"
+#include "ext4_crc32c.h"
 #include "ext4_fs.h"
 #include "ext4_blockdev.h"
 #include "ext4_block_group.h"
@@ -85,6 +86,37 @@
 	return (inode - 1) / inodes_per_group;
 }
 
+static uint32_t ext4_ialloc_bitmap_csum(struct ext4_sblock *sb,
+					void *bitmap)
+{
+	uint32_t checksum = 0;
+	if (ext4_sb_has_feature_read_only(sb,
+				EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+		/* First calculate crc32 checksum against fs uuid */
+		checksum = ext4_crc32c(~0, sb->uuid, sizeof(sb->uuid));
+		/* Then calculate crc32 checksum against block_group_desc */
+		checksum = ext4_crc32c(checksum, bitmap,
+				     ext4_sb_get_block_size(sb));
+	}
+	return checksum;
+}
+
+static void ext4_ialloc_set_bitmap_csum(struct ext4_sblock *sb,
+					struct ext4_bgroup *bg,
+					void *bitmap)
+{
+	int desc_size = ext4_sb_get_desc_size(sb);
+	uint32_t checksum = ext4_ialloc_bitmap_csum(sb, bitmap);
+	uint16_t lo_checksum = to_le16(checksum & 0xFFFF),
+		 hi_checksum = to_le16(checksum >> 16);
+	
+	/* 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;
+
+}
+
 int ext4_ialloc_free_inode(struct ext4_fs *fs, uint32_t index, bool is_dir)
 {
 	struct ext4_sblock *sb = &fs->sb;
@@ -110,6 +142,8 @@
 	uint32_t index_in_group = ext4_ialloc_inode2index_in_group(sb, index);
 	ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
 	bitmap_block.dirty = true;
+	ext4_ialloc_set_bitmap_csum(sb, bg_ref.block_group,
+				    bitmap_block.data);
 
 	/* Put back the block with bitmap */
 	rc = ext4_block_set(fs->bdev, &bitmap_block);
@@ -223,6 +257,8 @@
 
 			/* Free i-node found, save the bitmap */
 			bitmap_block.dirty = true;
+			ext4_ialloc_set_bitmap_csum(sb, bg_ref.block_group,
+						    bitmap_block.data);
 
 			ext4_block_set(fs->bdev, &bitmap_block);
 			if (rc != EOK) {