[Cluster-devel] [gfs2-utils PATCH] gfs2_edit: Add rgrepair option
Andrew Price
anprice at redhat.com
Tue Jan 10 16:59:06 UTC 2017
Hi Bob,
On 19/12/16 13:43, Bob Peterson wrote:
> Hi,
>
> This patch adds a new option, rgrepair, to gfs2_edit. Its purpose
> is to traverse all the resource groups in the rindex (assuming that
> the rindex is valid), and for each entry, verify it's really an rgrp,
> and that its bitmaps are bitmaps. If it finds an rgrp or bitmap block
> that's corrupt, it overwrites it with data that looks like a valid
> rgrp and/or bitmap. Then it looks for dinodes in that range of
> blocks. Any dinodes are marked as dinodes in the newly rewritten
> bitmap. Everything else is marked as a data block. That will allow
> fsck.gfs2 to try to straighten out the data from the free blocks.
>
> Signed-off-by: Bob Peterson <rpeterso at redhat.com>
Looks good to me - ACK
Andy
> ---
> diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
> index 40a719e..cd3f084 100644
> --- a/gfs2/edit/hexedit.c
> +++ b/gfs2/edit/hexedit.c
> @@ -2167,6 +2167,7 @@ static void usage(void)
> fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
> fprintf(stderr,"rgbitmaps <rgnum> - print out the bitmaps for rgrp "
> "rgnum.\n");
> + fprintf(stderr,"rgrepair - find and repair damaged rgrp.\n");
> fprintf(stderr,"-V prints version number.\n");
> fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
> fprintf(stderr,"-d prints details (for printing journals)\n");
> @@ -2259,6 +2260,135 @@ static void getgziplevel(char *argv[], int *i)
> (*i)++;
> }
>
> +static int count_dinode_blks(struct rgrp_tree *rgd, int bitmap,
> + struct gfs2_buffer_head *rbh)
> +{
> + struct gfs2_buffer_head *tbh;
> + uint64_t b;
> + int dinodes = 0;
> + char *byte, cur_state, new_state;
> + int bit, off;
> +
> + if (bitmap)
> + off = sizeof(struct gfs2_meta_header);
> + else
> + off = sizeof(struct gfs2_rgrp);
> +
> + for (b = 0; b < rgd->bits[bitmap].bi_len << GFS2_BIT_SIZE; b++) {
> + tbh = bread(&sbd, rgd->ri.ri_data0 +
> + rgd->bits[bitmap].bi_start + b);
> + byte = rbh->b_data + off + (b / GFS2_NBBY);
> + bit = (b % GFS2_NBBY) * GFS2_BIT_SIZE;
> + if (gfs2_check_meta(tbh, GFS2_METATYPE_DI) == 0) {
> + dinodes++;
> + new_state = GFS2_BLKST_DINODE;
> + } else {
> + new_state = GFS2_BLKST_USED;
> + }
> + cur_state = (*byte >> bit) & GFS2_BIT_MASK;
> + *byte ^= cur_state << bit;
> + *byte |= new_state << bit;
> + brelse(tbh);
> + }
> + bmodified(rbh);
> + return dinodes;
> +}
> +
> +static int count_dinode_bits(struct gfs2_buffer_head *rbh)
> +{
> + uint64_t blk;
> + struct gfs2_meta_header *mh = (struct gfs2_meta_header *)rbh->b_data;
> + char *byte;
> + int bit;
> + int dinodes = 0;
> +
> + if (be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG)
> + blk = sizeof(struct gfs2_rgrp);
> + else
> + blk = sizeof(struct gfs2_meta_header);
> +
> + for (; blk < sbd.bsize; blk++) {
> + byte = rbh->b_data + (blk / GFS2_NBBY);
> + bit = (blk % GFS2_NBBY) * GFS2_BIT_SIZE;
> + if (((*byte >> bit) & GFS2_BIT_MASK) == GFS2_BLKST_DINODE)
> + dinodes++;
> + }
> + return dinodes;
> +}
> +
> +static void rg_repair(void)
> +{
> + struct gfs2_buffer_head *rbh;
> + struct rgrp_tree *rgd;
> + struct osi_node *n;
> + int b;
> + int rgs_fixed = 0;
> + int dinodes_found = 0, dinodes_total = 0;
> +
> + /* Walk through the resource groups saving everything within */
> + for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
> + rgd = (struct rgrp_tree *)n;
> + if (gfs2_rgrp_read(&sbd, rgd) == 0) { /* was read in okay */
> + gfs2_rgrp_relse(rgd);
> + continue; /* ignore it */
> + }
> + /* If we get here, it's because we have an rgrp in the rindex
> + file that can't be read in. So attempt to repair it.
> + If we find a damaged rgrp or bitmap, fix the metadata.
> + Then scan all its blocks: if we find a dinode, set the
> + repaired bitmap to GFS2_BLKST_DINODE. Set all others to
> + GFS2_BLKST_USED so fsck can sort it out. If we set them
> + to FREE, fsck would just nuke it all. */
> + printf("Resource group at block %llu (0x%llx) appears to be "
> + "damaged. Attempting to fix it (in reverse order).\n",
> + (unsigned long long)rgd->ri.ri_addr,
> + (unsigned long long)rgd->ri.ri_addr);
> +
> + for (b = rgd->ri.ri_length - 1; b >= 0; b--) {
> + int mtype = (b ? GFS2_METATYPE_RB : GFS2_METATYPE_RG);
> + struct gfs2_meta_header *mh;
> +
> + printf("Bitmap #%d:", b);
> + rbh = bread(&sbd, rgd->ri.ri_addr + b);
> + if (gfs2_check_meta(rbh, mtype)) { /* wrong type */
> + printf("Damaged. Repairing...");
> + /* Fix the meta header */
> + memset(rbh->b_data, 0, sbd.bsize);
> + mh = (struct gfs2_meta_header *)rbh->b_data;
> + mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
> + mh->mh_type = cpu_to_be32(mtype);
> + if (b)
> + mh->mh_format =
> + cpu_to_be32(GFS2_FORMAT_RB);
> + else
> + mh->mh_format =
> + cpu_to_be32(GFS2_FORMAT_RG);
> + bmodified(rbh);
> + /* Count the dinode blocks */
> + dinodes_found = count_dinode_blks(rgd, b, rbh);
> + } else { /* bitmap info is okay: tally it. */
> + printf("Undamaged. Analyzing...");
> + dinodes_found = count_dinode_bits(rbh);
> + }
> + printf("Dinodes found: %d\n", dinodes_found);
> + dinodes_total += dinodes_found;
> + if (b == 0) { /* rgrp itself was damaged */
> + rgd->rg.rg_dinodes = dinodes_total;
> + rgd->rg.rg_free = 0;
> + }
> + brelse(rbh);
> + }
> + rgs_fixed++;
> + }
> + if (rgs_fixed)
> + printf("%d resource groups fixed.\n"
> + "You should run fsck.gfs2 to reconcile the bitmaps.\n",
> + rgs_fixed);
> + else
> + printf("All resource groups are okay. No repairs needed.\n");
> + exit(0);
> +}
> +
> /* ------------------------------------------------------------------------ */
> /* parameterpass1 - pre-processing for command-line parameters */
> /* ------------------------------------------------------------------------ */
> @@ -2307,6 +2437,8 @@ static void parameterpass1(int argc, char *argv[], int i)
> termlines = 0;
> else if (!strcmp(argv[i], "rgflags"))
> termlines = 0;
> + else if (!strcmp(argv[i], "rgrepair"))
> + termlines = 0;
> else if (!strcmp(argv[i], "rg"))
> termlines = 0;
> else if (!strcasecmp(argv[i], "-x"))
> @@ -2483,6 +2615,8 @@ static void process_parameters(int argc, char *argv[], int pass)
> for (bmap = 0; bmap < rgd->ri.ri_length; bmap++)
> push_block(rgblk + bmap);
> }
> + else if (!strcmp(argv[i], "rgrepair"))
> + rg_repair();
> else if (!strcasecmp(argv[i], "savemeta")) {
> getgziplevel(argv, &i);
> savemeta(argv[i+2], 0, gziplevel);
>
More information about the Cluster-devel
mailing list