[Ocfs2-tools-devel] [PATCH 08/12] libocfs2: Add support for metadata checksums and error correction.

Joel Becker joel.becker at oracle.com
Mon Dec 29 19:23:44 PST 2008


Use the functions in blockcheck.[ch] to add checksums and error
correction to libocfs2.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 libocfs2/chain.c          |    5 +++++
 libocfs2/dirblock.c       |   13 +++++++++----
 libocfs2/extents.c        |    5 +++++
 libocfs2/feature_string.c |   12 +++++++++++-
 libocfs2/inode.c          |    4 ++++
 libocfs2/openfs.c         |   37 +++++++++++++++++++++++++++++++++----
 6 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/libocfs2/chain.c b/libocfs2/chain.c
index 7af61fe..e9d3873 100644
--- a/libocfs2/chain.c
+++ b/libocfs2/chain.c
@@ -67,6 +67,10 @@ errcode_t ocfs2_read_group_desc(ocfs2_filesys *fs, uint64_t blkno,
 
 	gd = (struct ocfs2_group_desc *)blk;
 
+	ret = ocfs2_validate_meta_ecc(fs, blk, &gd->bg_check);
+	if (ret)
+		goto out;
+
 	ret = OCFS2_ET_BAD_GROUP_DESC_MAGIC;
 	if (memcmp(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
 		   strlen(OCFS2_GROUP_DESC_SIGNATURE)))
@@ -107,6 +111,7 @@ errcode_t ocfs2_write_group_desc(ocfs2_filesys *fs, uint64_t blkno,
 	gd = (struct ocfs2_group_desc *)blk;
 	ocfs2_swap_group_desc(gd);
 
+	ocfs2_compute_meta_ecc(fs, blk, &gd->bg_check);
 	ret = io_write_block(fs->fs_io, blkno, 1, blk);
 	if (ret)
 		goto out;
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index d1a9a45..fec8ffc 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -54,12 +54,12 @@ int ocfs2_dir_has_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di)
 	    (di->i_dyn_features & OCFS2_INLINE_DATA_FL))
 		return 0;
 
-	return 0;
+	return ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super));
 }
 
 int ocfs2_supports_dir_trailer(ocfs2_filesys *fs)
 {
-	return 0;
+	return ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super));
 }
 
 int ocfs2_skip_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
@@ -165,6 +165,10 @@ errcode_t ocfs2_read_dir_block(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 		end = ocfs2_dir_trailer_blk_off(fs);
 		trailer = ocfs2_dir_trailer_from_block(fs, buf);
 
+		retval = ocfs2_validate_meta_ecc(fs, buf, &trailer->db_check);
+		if (retval)
+			goto out;
+
 		if (memcmp(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE,
 			   strlen(OCFS2_DIR_TRAILER_SIGNATURE))) {
 			retval = OCFS2_ET_BAD_DIR_BLOCK_MAGIC;
@@ -205,13 +209,14 @@ errcode_t ocfs2_write_dir_block(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 		goto out;
 	
 	/*
-	 * We can always set trailer - Nothing happens if it isn't actually
-	 * used.
+	 * We can always set trailer - ocfs2_compute_meta_ecc() does
+	 * nothing if the filesystem doesn't have the feature turned on
 	 */
 	trailer = ocfs2_dir_trailer_from_block(fs, buf);
 	if (ocfs2_dir_has_trailer(fs, di))
 		ocfs2_swap_dir_trailer(trailer);
 
+	ocfs2_compute_meta_ecc(fs, buf, &trailer->db_check);
  	retval = io_write_block(fs->fs_io, block, 1, buf);
 out:
 	ocfs2_free(&buf);
diff --git a/libocfs2/extents.c b/libocfs2/extents.c
index 51b1aae..5f16789 100644
--- a/libocfs2/extents.c
+++ b/libocfs2/extents.c
@@ -124,6 +124,10 @@ errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs,
 
 	eb = (struct ocfs2_extent_block *)blk;
 
+	ret = ocfs2_validate_meta_ecc(fs, blk, &eb->h_check);
+	if (ret)
+		goto out;
+
 	if (memcmp(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE,
 		   strlen(OCFS2_EXTENT_BLOCK_SIGNATURE))) {
 		ret = OCFS2_ET_BAD_EXTENT_BLOCK_MAGIC;
@@ -179,6 +183,7 @@ errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
 	eb = (struct ocfs2_extent_block *) blk;
 	ocfs2_swap_extent_block_from_cpu(eb);
 
+	ocfs2_compute_meta_ecc(fs, blk, &eb->h_check);
 	ret = io_write_block(fs->fs_io, blkno, 1, blk);
 	if (ret)
 		goto out;
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index 7b1f93e..56618db 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -72,7 +72,8 @@ static ocfs2_fs_options feature_level_defaults[] = {
 	{OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
 	 OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
 	 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP |
-	 OCFS2_FEATURE_INCOMPAT_INLINE_DATA,
+	 OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
+	 OCFS2_FEATURE_INCOMPAT_META_ECC,
 	 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
 };
 
@@ -110,6 +111,11 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
 		{0, OCFS2_FEATURE_INCOMPAT_INLINE_DATA, 0},
 	},
 	{
+		"metaecc",
+		{0, OCFS2_FEATURE_INCOMPAT_META_ECC, 0},
+		{0, OCFS2_FEATURE_INCOMPAT_META_ECC, 0},
+	},
+	{
 		NULL,
 		{0, 0, 0},
 		{0, 0, 0}
@@ -169,6 +175,10 @@ static struct feature_name ocfs2_feature_names[] = {
 		.fn_flag = {OCFS2_FEATURE_COMPAT_JBD2_SB, 0, 0},
 	},
 	{
+		.fn_name = "MetaECC",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_META_ECC, 0},
+	},
+	{
 		.fn_name = NULL,
 	},
 };
diff --git a/libocfs2/inode.c b/libocfs2/inode.c
index d351658..25d14b7 100644
--- a/libocfs2/inode.c
+++ b/libocfs2/inode.c
@@ -256,6 +256,9 @@ errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
 		goto out;
 
 	di = (struct ocfs2_dinode *)blk;
+	ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check);
+	if (ret)
+		goto out;
 
 	ret = OCFS2_ET_BAD_INODE_MAGIC;
 	if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
@@ -297,6 +300,7 @@ errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
 	di = (struct ocfs2_dinode *)blk;
 	ocfs2_swap_inode_from_cpu(di);
 
+	ocfs2_compute_meta_ecc(fs, blk, &di->i_check);
 	ret = io_write_block(fs->fs_io, blkno, 1, blk);
 	if (ret)
 		goto out;
diff --git a/libocfs2/openfs.c b/libocfs2/openfs.c
index 4044757..0f6d048 100644
--- a/libocfs2/openfs.c
+++ b/libocfs2/openfs.c
@@ -102,8 +102,10 @@ out:
 errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
 {
 	errcode_t ret;
-	char *blk;
-	struct ocfs2_dinode *di;
+	char *blk, *swapblk;
+	struct ocfs2_dinode *di, *orig_super;
+	int orig_blocksize;
+	int blocksize = io_get_blksize(fs->fs_io);
 
 	ret = ocfs2_malloc_block(fs->fs_io, &blk);
 	if (ret)
@@ -112,6 +114,7 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
 	ret = ocfs2_read_blocks(fs, superblock, 1, blk);
 	if (ret)
 		goto out_blk;
+
 	di = (struct ocfs2_dinode *)blk;
 
 	ret = OCFS2_ET_BAD_MAGIC;
@@ -119,8 +122,33 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
 		   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)))
 		goto out_blk;
 
-	ocfs2_swap_inode_to_cpu(di);
+	/*
+	 * We want to use the latest superblock to validate.  We need
+	 * a local-endian copy in fs->fs_super, and the unswapped copy to
+	 * check in blk.  ocfs2_validate_meta_ecc() uses fs->fs_super and
+	 * fs->fs_blocksize.
+	 */
+	ret = ocfs2_malloc_block(fs->fs_io, &swapblk);
+	if (ret)
+		goto out_blk;
 
+	memcpy(swapblk, blk, blocksize);
+	orig_super = fs->fs_super;
+	orig_blocksize = fs->fs_blocksize;
+	fs->fs_super = (struct ocfs2_dinode *)swapblk;
+	fs->fs_blocksize = blocksize;
+	ocfs2_swap_inode_to_cpu(fs->fs_super);
+
+	ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check);
+
+	fs->fs_super = orig_super;
+	fs->fs_blocksize = orig_blocksize;
+	ocfs2_free(&swapblk);
+
+	if (ret)
+		goto out_blk;
+
+	ocfs2_swap_inode_to_cpu(di);
 	if (!sb)
 		fs->fs_super = di;
 	else {
@@ -288,7 +316,8 @@ errcode_t ocfs2_open(const char *name, int flags,
 				io_set_blksize(fs->fs_io, block_size);
 				ret = ocfs2_read_super(fs, (uint64_t)superblock,
 						       NULL);
-				if (ret == OCFS2_ET_BAD_MAGIC)
+				if ((ret == OCFS2_ET_BAD_MAGIC) ||
+				    (ret == OCFS2_ET_IO))
 					continue;
 				break;
 			}
-- 
1.5.6.5




More information about the Ocfs2-tools-devel mailing list