[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