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

Tao Ma tao.ma at oracle.com
Wed Jul 21 00:31:38 PDT 2010


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);
+	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);
+
+	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
-- 
1.7.1.GIT




More information about the Ocfs2-tools-devel mailing list