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

Sunil Mushran sunil.mushran at oracle.com
Wed Jan 7 17:44:50 PST 2009


Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>

Joel Becker wrote:
> 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;
>  			}
>   




More information about the Ocfs2-tools-devel mailing list