[Ocfs2-tools-devel] [PATCH 3/3] fswreck: Add corrupt codes for extent list check.

tristan tristan.ye at oracle.com
Wed Jul 21 02:14:36 PDT 2010


Tao Ma wrote:
> Signed-off-by: Tao Ma <tao.ma at oracle.com>
> ---
>  fswreck/Makefile               |    5 +-
>  fswreck/corrupt.c              |    6 +
>  fswreck/discontig_bg.c         |  270 ++++++++++++++++++++++++++++++++++++++++
>  fswreck/include/corrupt.h      |    2 +
>  fswreck/include/discontig_bg.h |   23 ++++
>  fswreck/include/fsck_type.h    |    9 ++
>  fswreck/include/main.h         |    1 +
>  fswreck/main.c                 |   18 +++
>  8 files changed, 332 insertions(+), 2 deletions(-)
>  create mode 100644 fswreck/discontig_bg.c
>  create mode 100644 fswreck/include/discontig_bg.h
>
> diff --git a/fswreck/Makefile b/fswreck/Makefile
> index 65dffd6..b1ee546 100644
> --- a/fswreck/Makefile
> +++ b/fswreck/Makefile
> @@ -10,7 +10,7 @@ INCLUDES += $(GLIB_CFLAGS)
>  
>  UNINST_PROGRAMS = fswreck
>  
> -CFILES = main.c corrupt.c chain.c extent.c group.c inode.c local_alloc.c truncate_log.c special.c symlink.c dir.c journal.c quota.c refcount.c
> +CFILES = main.c corrupt.c chain.c extent.c group.c inode.c local_alloc.c truncate_log.c special.c symlink.c dir.c journal.c quota.c refcount.c discontig_bg.c
>  
>  HFILES = 			\
>  	include/chain.h		\
> @@ -27,7 +27,8 @@ HFILES = 			\
>  	include/main.h		\
>  	include/symlink.h	\
>  	include/quota.h		\
> -	include/refcount.h
> +	include/refcount.h	\
> +	include/discontig_bg.h
>  
>  DIST_FILES = $(CFILES) $(HFILES)
>  DIST_RULES = dist-subdircreate
> diff --git a/fswreck/corrupt.c b/fswreck/corrupt.c
> index a724268..aa76dcc 100644
> --- a/fswreck/corrupt.c
> +++ b/fswreck/corrupt.c
> @@ -456,3 +456,9 @@ void corrupt_refcount(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum)
>  
>  	return;
>  }
> +
> +void corrupt_discontig_bg(ocfs2_filesys *fs, enum fsck_type type,
> +			  uint16_t slotnum)
> +{
> +	mess_up_discontig_bg(fs, type, slotnum);
> +}
> diff --git a/fswreck/discontig_bg.c b/fswreck/discontig_bg.c
> new file mode 100644
> index 0000000..3e15055
> --- /dev/null
> +++ b/fswreck/discontig_bg.c
> @@ -0,0 +1,270 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * discontig_bg.c
> + *
> + * Copyright (C) 2010 Oracle.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <assert.h>
> +#include "main.h"
> +
> +extern char *progname;
> +
> +static void create_discontig_bg_list(ocfs2_filesys *fs,
> +				     struct ocfs2_group_desc *gd,
> +				     uint64_t blkno,
> +				     uint32_t clusters)
> +{
> +	uint16_t recs = ocfs2_extent_recs_per_gd(fs->fs_blocksize) / 2;
> +	int i, clusters_per_rec, cpos = 0;
> +	struct ocfs2_extent_rec *rec;
> +
> +	/* Calculate out how much clusters one rec have and how many
> +	 * recs we have.
> +	 */
> +	if (clusters > recs)
> +		clusters_per_rec = clusters / recs;
> +	else {
> +		recs = clusters;
> +		clusters_per_rec = 1;
> +	}
> +
> +	for (i = 0; i < recs - 1; i++) {
> +		rec = &gd->bg_list.l_recs[i];
> +
> +		rec->e_blkno = blkno;
> +		rec->e_cpos = cpos;
> +		rec->e_leaf_clusters = clusters_per_rec;
> +		blkno += ocfs2_clusters_to_blocks(fs, clusters_per_rec);
> +		cpos += clusters_per_rec;
> +	}
> +
> +	/* Set the last rec according to all the clusters left. */
> +	rec = &gd->bg_list.l_recs[recs - 1];
> +	rec->e_blkno = blkno;
> +	rec->e_cpos = cpos;
> +	rec->e_leaf_clusters = clusters - (recs - 1) * clusters_per_rec;
> +
> +	gd->bg_list.l_count = ocfs2_extent_recs_per_gd(fs->fs_blocksize);
> +	gd->bg_list.l_tree_depth = 0;
> +	gd->bg_list.l_next_free_rec = recs;
> +}
> +
> +/*
> + * Add a new discontig inode alloc group to the given slot.
> + * the buf will contain the new created alloc group.
> + */
> +static void create_discontig_bg(ocfs2_filesys *fs,
> +				uint16_t slotnum,
> +				char *gd_buf)
> +{
> +	char *buf = NULL;
> +	errcode_t ret;
> +	char sysfile[OCFS2_MAX_FILENAME_LEN];
> +	struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
> +	struct ocfs2_chain_list *cl;
> +	struct ocfs2_dinode *di;
> +	struct ocfs2_group_desc *gd;
> +	struct ocfs2_chain_rec *rec;
> +	uint32_t clusters;
> +	uint64_t gd_blkno, di_blkno, old_blkno;
> +	uint16_t chain;
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	if (slotnum == UINT16_MAX)
> +		slotnum = 0;
> +
> +	snprintf(sysfile, sizeof(sysfile),
> +		ocfs2_system_inodes[INODE_ALLOC_SYSTEM_INODE].si_name,
> +		slotnum);
> +
> +	ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, sysfile,
> +			   strlen(sysfile), NULL, &di_blkno);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	ret = ocfs2_read_inode(fs, di_blkno, buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	di = (struct ocfs2_dinode *)buf;
> +	cl = &di->id2.i_chain;
> +
> +	chain = cl->cl_next_free_rec;
> +	if (chain == cl->cl_count)
> +		chain = 0;
> +
> +	ret = ocfs2_new_clusters(fs, cl->cl_cpg, cl->cl_cpg,
> +				 &gd_blkno, &clusters);

Hi tao,

You are trying to create a contiguous block group here:) Actually we'll 
still have a chance to proceed even if ocfs2_new_clusters failed to 
allocate a contiguous region of clusters. how about using following 
strategy:?

/*
* we know there is 244 extent records in discontig-bg at most for sure
*/
uint64_t clusters_region_blknos[244];
uint32_t wanted_clusters, left_clusters, cluster_regions = 0;
int i = 0;

ret = ocfs2_malloc_block(&gd_blkno,...);

wanted_clusters = cl->cl_cpg;
left_clusters = wanted_clusters;

while (left_clusters) {

ret = ocfs2_new_clusters(fs, wanted_clusters, &cluster_region_blknos[i]);
if (ret == -ENOMEM) {
if (allocsize == OCFS2_CLUSTERSIZE)
FSWRK_COM_FATAL(Programe, ret);

wanted_clusters >>= 1;

}

left_clusters -= wanted_clusters;
i++;
}

cluster_regions = i;

/*
* Then we pass the array clusters_region_blknos[] and its size to 
'create_discontig_bg_list'
* so that it can fill its extent list by array members.
*/

That way, we're doing in a more 'discontig' way:)

> +	if (ret || (clusters != cl->cl_cpg))
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	gd = (struct ocfs2_group_desc *)gd_buf;
> +	ocfs2_init_group_desc(fs, gd, gd_blkno, fs->fs_super->i_fs_generation,
> +			      di->i_blkno,
> +			      di->id2.i_chain.cl_cpg * di->id2.i_chain.cl_bpc,
> +			      chain, 1);
> +
> +	create_discontig_bg_list(fs, gd, gd_blkno, clusters);
> +
> +	rec = &di->id2.i_chain.cl_recs[chain];
> +	old_blkno = rec->c_blkno;
> +	gd->bg_next_group = old_blkno;
> +
> +	ret = ocfs2_write_group_desc(fs, gd_blkno, gd_buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);

Suddenly, I found there may be a memory leak all around the fswreck 
codes, if we exit there by FSWRK_COM_FATAL,
We've just got no chance to free the 'buf'.

> +
> +	rec->c_free += gd->bg_free_bits_count;
> +	rec->c_total += gd->bg_bits;
> +	rec->c_blkno = gd_blkno;
> +
> +	di->i_clusters += di->id2.i_chain.cl_cpg;
> +	di->i_size = (uint64_t)di->i_clusters * fs->fs_clustersize;
> +	di->id1.bitmap1.i_total += gd->bg_bits;
> +	di->id1.bitmap1.i_used += gd->bg_bits -	gd->bg_free_bits_count;
> +	if (di->id2.i_chain.cl_next_free_rec == chain)
> +		di->id2.i_chain.cl_next_free_rec = chain + 1;
> +
> +	ret = ocfs2_write_inode(fs, di_blkno, buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	ocfs2_free(&buf);
> +}
> +
> +void mess_up_discontig_bg(ocfs2_filesys *fs, enum fsck_type type,
> +			  uint16_t slotnum)
> +{
> +	errcode_t ret;
> +	char *buf = NULL;
> +	struct ocfs2_group_desc *gd;
> +	uint16_t old;
> +	uint32_t old_clusters, old_clusters1;
> +	uint64_t old_blkno;
> +
> +	if (!ocfs2_supports_discontig_bg(OCFS2_RAW_SB(fs->fs_super)))
> +		FSWRK_FATAL("Should specify a discontig-bg supported "
> +			    "volume to do this corruption\n");
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +
> +	create_discontig_bg(fs, slotnum, buf);
> +
> +	gd = (struct ocfs2_group_desc *)buf;
> +
> +	switch (type) {
> +	case DISCONTIG_BG_DEPTH:
> +		old = gd->bg_list.l_tree_depth;
> +		gd->bg_list.l_tree_depth++;
> +		fprintf(stdout, "DISCONTIG_BG_DEPTH: Corrupt discontig bg #"
> +			"%"PRIu64", change l_tree_depth from %u to %u\n",
> +			(uint64_t)gd->bg_blkno, old, gd->bg_list.l_tree_depth);
> +		break;
> +	case DISCONTIG_BG_COUNT:
> +		old = gd->bg_list.l_count;
> +		gd->bg_list.l_count += 10;;
> +		fprintf(stdout, "DISCONTIG_BG_COUNT: Corrupt discontig bg #"
> +			"%"PRIu64", change l_count from %u to %u\n",
> +			(uint64_t)gd->bg_blkno, old, gd->bg_list.l_count);
> +		break;
> +	case DISCONTIG_BG_REC_RANGE:
> +		old_blkno = gd->bg_list.l_recs[0].e_blkno;
> +		gd->bg_list.l_recs[0].e_blkno = fs->fs_blocks + 10;
> +		fprintf(stdout, "DISCONTIG_BG_REC_RANGE: Corrupt discontig bg #"
> +			"%"PRIu64", change recs[0].e_blkno from %"PRIu64
> +			" to %"PRIu64"\n",
> +			(uint64_t)gd->bg_blkno, old_blkno,
> +			(uint64_t)gd->bg_list.l_recs[0].e_blkno);
> +		break;
> +	case DISCONTIG_BG_CORRUPT_LEAFS:
> +		old_clusters = gd->bg_list.l_recs[0].e_leaf_clusters;
> +		old_clusters1 = gd->bg_list.l_recs[1].e_leaf_clusters;
> +		gd->bg_list.l_recs[0].e_leaf_clusters = fs->fs_clusters;
> +		gd->bg_list.l_recs[1].e_leaf_clusters = fs->fs_clusters;
> +		fprintf(stdout, "DISCONTIG_BG_CORRUPT_LEAFS: Corrupt discontig"
> +			" bg #%"PRIu64", change recs[0] clusters from %u to %u,"
> +			" change recs1[1] clusters from %u to %u\n",
> +			(uint64_t)gd->bg_blkno,
> +			old_clusters, gd->bg_list.l_recs[0].e_leaf_clusters,
> +			old_clusters1, gd->bg_list.l_recs[1].e_leaf_clusters);
> +		break;
> +	case DISCONTIG_BG_CLUSTERS:
> +		old_clusters = gd->bg_list.l_recs[0].e_leaf_clusters;
> +		gd->bg_list.l_recs[0].e_leaf_clusters += 1;
> +		fprintf(stdout, "DISCONTIG_BG_CORRUPT_LEAFS: Corrupt discontig"
> +			" bg #%"PRIu64", change recs[0] clusters from %u to "
> +			"%u\n",	(uint64_t)gd->bg_blkno,
> +			old_clusters, gd->bg_list.l_recs[0].e_leaf_clusters);
> +		break;
> +	case DISCONTIG_BG_NEXT_FREE_REC:
> +		old = gd->bg_list.l_next_free_rec;
> +		gd->bg_list.l_next_free_rec += 10;;
> +		fprintf(stdout, "DISCONTIG_BG_NEXT_FREE_REC: Corrupt discontig "
> +			"bg #%"PRIu64", change l_next_free_rec from %u to %u\n",
> +			(uint64_t)gd->bg_blkno,
> +			old, gd->bg_list.l_next_free_rec);
> +		break;
> +	case DISCONTIG_BG_LIST_CORRUPT:
> +		old = gd->bg_list.l_next_free_rec;
> +		gd->bg_list.l_next_free_rec += 10;
> +		old_clusters = gd->bg_list.l_recs[0].e_leaf_clusters;
> +		gd->bg_list.l_recs[0].e_leaf_clusters = fs->fs_clusters;
> +		fprintf(stdout, "DISCONTIG_BG_NEXT_FREE_REC: Corrupt discontig "
> +			"bg #%"PRIu64", change l_next_free_rec from %u to %u, "
> +			"change recs[0] cluster from %u to %u\n",
> +			(uint64_t)gd->bg_blkno,
> +			old, gd->bg_list.l_next_free_rec,
> +			old_clusters, gd->bg_list.l_recs[0].e_leaf_clusters);
> +		break;
> +	case DISCONTIG_BG_REMOVE_REC:
> +		/*
> +		 * Just add one more record, make its e_blkno looks sane,
> +		 * while the e_leaf_clusters is insane.
> +		 */
> +		old = gd->bg_list.l_next_free_rec;
> +		gd->bg_list.l_next_free_rec += 1;
> +		gd->bg_list.l_recs[old].e_blkno = 65536;
> +		gd->bg_list.l_recs[old].e_leaf_clusters = fs->fs_clusters;
> +		fprintf(stdout, "DISCONTIG_BG_NEXT_FREE_REC: Corrupt discontig "
> +			"bg #%"PRIu64", change l_next_free_rec from %u to %u,"
> +			"add new rec start %"PRIu64", cluster %u\n",
> +			(uint64_t)gd->bg_blkno,
> +			old, gd->bg_list.l_next_free_rec,
> +			(uint64_t)gd->bg_list.l_recs[old].e_blkno,
> +			gd->bg_list.l_recs[old].e_leaf_clusters);
> +		break;
> +	case DISCONTIG_BG_LEAF_CLUSTERS:
> +		old_clusters = gd->bg_list.l_recs[0].e_leaf_clusters;
> +		gd->bg_list.l_recs[0].e_leaf_clusters = fs->fs_clusters;
> +		fprintf(stdout, "DISCONTIG_BG_CORRUPT_LEAFS: Corrupt discontig"
> +			" bg #%"PRIu64", change recs[0] clusters from %u to "
> +			"%u\n",	(uint64_t)gd->bg_blkno,
> +			old_clusters, gd->bg_list.l_recs[0].e_leaf_clusters);
> +		break;
> +	default:
> +		FSWRK_FATAL("Invalid type[%d]\n", type);
> +	}
> +
> +	ret = ocfs2_write_group_desc(fs, gd->bg_blkno, buf);
> +	if (ret)
> +		FSWRK_COM_FATAL(progname, ret);
> +	ocfs2_free(&buf);
> +
> +	return;
> +}
> diff --git a/fswreck/include/corrupt.h b/fswreck/include/corrupt.h
> index ae7917c..0fb7193 100644
> --- a/fswreck/include/corrupt.h
> +++ b/fswreck/include/corrupt.h
> @@ -35,5 +35,7 @@ void corrupt_local_alloc(ocfs2_filesys *fs, enum fsck_type type,
>  void corrupt_truncate_log(ocfs2_filesys *fs, enum fsck_type type,
>  			  uint16_t slotnum);
>  void corrupt_refcount(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum);
> +void corrupt_discontig_bg(ocfs2_filesys *fs, enum fsck_type type,
> +			  uint16_t slotnum);
>  
>  #endif		/* __CORRUPT_H */
> diff --git a/fswreck/include/discontig_bg.h b/fswreck/include/discontig_bg.h
> new file mode 100644
> index 0000000..9e93816
> --- /dev/null
> +++ b/fswreck/include/discontig_bg.h
> @@ -0,0 +1,23 @@
> +/*
> + * discontig_bg.h
> + *
> + * Function prototypes, macros, etc. for related 'C' files
> + *
> + * Copyright (C) 2010 Oracle.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + */
> +
> +#ifndef _FSWRECK_DISCONTIG_BG_H_
> +#define _FSWRECK_DISCONTIG_BG_H_
> +
> +void mess_up_discontig_bg(ocfs2_filesys *fs, enum fsck_type type,
> +			  uint16_t slotnum);
> +#endif		/* _FSWRECK_DISCONTIG_BG_H_ */
> diff --git a/fswreck/include/fsck_type.h b/fswreck/include/fsck_type.h
> index 99961cc..8a0e9b6 100644
> --- a/fswreck/include/fsck_type.h
> +++ b/fswreck/include/fsck_type.h
> @@ -66,6 +66,15 @@ enum fsck_type
>  	CHAIN_LINK_MAGIC,
>  	CHAIN_LINK_RANGE,
>  	CHAIN_BITS,
> +	DISCONTIG_BG_DEPTH,
> +	DISCONTIG_BG_COUNT,
> +	DISCONTIG_BG_REC_RANGE,
> +	DISCONTIG_BG_CORRUPT_LEAFS,
> +	DISCONTIG_BG_CLUSTERS,
> +	DISCONTIG_BG_NEXT_FREE_REC,
> +	DISCONTIG_BG_LIST_CORRUPT,
> +	DISCONTIG_BG_REMOVE_REC,
> +	DISCONTIG_BG_LEAF_CLUSTERS,
>  	INODE_ALLOC_REPAIR,
>  	INODE_SUBALLOC,
>  	LALLOC_SIZE,
> diff --git a/fswreck/include/main.h b/fswreck/include/main.h
> index 94682f4..3175305 100644
> --- a/fswreck/include/main.h
> +++ b/fswreck/include/main.h
> @@ -91,5 +91,6 @@
>  #include "journal.h"
>  #include "quota.h"
>  #include "refcount.h"
> +#include "discontig_bg.h"
>  
>  #endif		/* __MAIN_H__ */
> diff --git a/fswreck/main.c b/fswreck/main.c
> index 76c3039..57b0ebc 100644
> --- a/fswreck/main.c
> +++ b/fswreck/main.c
> @@ -296,6 +296,24 @@ static struct prompt_code prompt_codes[NUM_FSCK_TYPE] = {
>  			   "corrupt the refcount record in a refcount block"),
>  	define_prompt_code(DUP_CLUSTERS_ADD_REFCOUNT, corrupt_refcount,
>  			   "corrupt refcount record and handle them in dup"),
> +	define_prompt_code(DISCONTIG_BG_DEPTH, corrupt_discontig_bg,
> +			   "corrupt extent tree depth for a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_COUNT, corrupt_discontig_bg,
> +			   "corrupt extent list count for a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_REC_RANGE, corrupt_discontig_bg,
> +			   "corrupt extent rec range for a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_CORRUPT_LEAFS, corrupt_discontig_bg,
> +			   "corrupt extent recs' clusters for a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_CLUSTERS, corrupt_discontig_bg,
> +			   "corrupt a discontig bg by more clusters allocated"),
> +	define_prompt_code(DISCONTIG_BG_NEXT_FREE_REC, corrupt_discontig_bg,
> +			   "corrupt extent list's next free of a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_LIST_CORRUPT, corrupt_discontig_bg,
> +			   "corrupt extent list and rec for  a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_REMOVE_REC, corrupt_discontig_bg,
> +			   "corrupt extent rec for a discontig bg"),
> +	define_prompt_code(DISCONTIG_BG_LEAF_CLUSTERS, corrupt_discontig_bg,
> +			   "corrupt extent rec's clusters for a discontig bg"),
>  };
>  
>  #undef define_prompt_code




More information about the Ocfs2-tools-devel mailing list