[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