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

tristan tristan.ye at oracle.com
Wed Jul 21 02:22:18 PDT 2010


tristan wrote:
> 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++;
> }

Oh, I hate thunderbird eating my indentations up, let me try again to 
paste the codes in another format.

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;
continue;
}

left_clusters -= wanted_clusters;
i++;
}

cluster_regions = i;


Sorry for the terrible readability.
>
> 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