From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20367 invoked by alias); 19 Jun 2009 20:59:10 -0000 Received: (qmail 20352 invoked by alias); 19 Jun 2009 20:59:10 -0000 X-SWARE-Spam-Status: No, hits=-0.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_21,J_CHICKENPOX_23,J_CHICKENPOX_45,SPF_HELO_PASS X-Spam-Status: No, hits=-0.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_21,J_CHICKENPOX_23,J_CHICKENPOX_45,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bastion2.fedora.phx.redhat.com Subject: gfs2-utils: master - fsck.gfs2 writing bitmap when -n specified To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: gfs2-utils.git X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 47b37cfb7beba33018d18d96eb754910112615a8 X-Git-Newrev: 6f706bf2d51acdf0c00e93f3f55baf49e4f5114c From: Bob Peterson Message-Id: <20090619205839.DFDA81201D2@lists.fedorahosted.org> Date: Fri, 19 Jun 2009 20:59:00 -0000 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2009-q2/txt/msg00571.txt.bz2 Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=6f706bf2d51acdf0c00e93f3f55baf49e4f5114c Commit: 6f706bf2d51acdf0c00e93f3f55baf49e4f5114c Parent: 47b37cfb7beba33018d18d96eb754910112615a8 Author: Bob Peterson AuthorDate: Fri Jun 19 15:55:45 2009 -0500 Committer: Bob Peterson CommitterDate: Fri Jun 19 15:55:45 2009 -0500 fsck.gfs2 writing bitmap when -n specified bz 500483 The previous patch was updating the bitmap for all data blocks. That's not desired, especially when -n is specified. This version checks the type in the existing bitmap first to see whether it needs changing, and if so, it asks permission to do so. This required the use of a function that was once in libgfs2 but it eventually found its way to gfs2_edit. Now it's back in libgfs2 so multiple utils can use it. --- gfs2/edit/hexedit.c | 61 ------------------------------------------------ gfs2/fsck/pass1.c | 53 +++++++++++++++++++++++++++++++---------- gfs2/libgfs2/fs_bits.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ gfs2/libgfs2/libgfs2.h | 2 + 4 files changed, 103 insertions(+), 74 deletions(-) diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index e8c6030..f9b9bb4 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -446,67 +446,6 @@ static int get_block_type(const char *lpBuffer) return ret_type; } -/* - * fs_get_bitmap - get value of FS bitmap - * @sdp: super block - * @blkno: block number relative to file system - * - * This function gets the value of a bit of the - * file system bitmap. - * Possible state values for a block in the bitmap are: - * GFS_BLKST_FREE (0) - * GFS_BLKST_USED (1) - * GFS_BLKST_INVALID (2) - * GFS_BLKST_DINODE (3) - * - * Returns: state on success, -1 on error - */ -static int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, - struct rgrp_list *rgd) -{ - int i, val; - uint32_t rgrp_block; - struct gfs2_bitmap *bits = NULL; - unsigned int bit; - unsigned char *byte; - int local_rgd = 0; - - if(gfs2_check_range(sdp, blkno)) - return -1; - if(rgd == NULL) { - local_rgd = 1; - rgd = gfs2_blk2rgrpd(sdp, blkno); - } - if(rgd == NULL) - return -1; - if(gfs2_rgrp_read(sdp, rgd)) - return -1; - - rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0); - - for(i= 0; i < rgd->ri.ri_length; i++){ - bits = &(rgd->bits[i]); - if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY)){ - break; - } - } - - if(i >= rgd->ri.ri_length){ - gfs2_rgrp_relse(rgd, not_updated); - return -1; - } - - byte = (unsigned char *)(rgd->bh[i]->b_data + bits->bi_offset) + - (rgrp_block/GFS2_NBBY - bits->bi_start); - bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE; - - val = ((*byte >> bit) & GFS2_BIT_MASK); - if(local_rgd) - gfs2_rgrp_relse(rgd, not_updated); - - return val; -} - /* ------------------------------------------------------------------------ */ /* display_block_type */ /* returns: metatype if block is a GFS2 structure block type */ diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 1a635b6..2bcf1f8 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -137,7 +137,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) { struct gfs2_block_query q = {0}; struct block_count *bc = (struct block_count *) private; - int error = 0; + int error = 0, btype; if (gfs2_check_range(ip->i_sbd, block)) { log_err( _("Bad data block pointer (out of range)\n")); @@ -168,17 +168,14 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) won't have metadata headers. In that case, the block is marked as duplicate, but also as a data block. */ error = 1; - log_err( _("Block %" PRIu64 " (0x%"PRIx64 ") previous " - "reference was invalid, so it likely is a data " - "block.\n"), - block, block); gfs2_block_unmark(ip->i_sbd, bl, block, gfs2_meta_inval); gfs2_block_mark(ip->i_sbd, bl, block, gfs2_dup_block); } - log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to data block\n"), block, - block); + log_debug( _("Marking block %llu (0x%llx) as data block\n"), + (unsigned long long)block, (unsigned long long)block); gfs2_block_mark(ip->i_sbd, bl, block, gfs2_block_used); - /* This is confusing, so I'll clarify. There are two bitmaps: + + /* This is also confusing, so I'll clarify. There are two bitmaps: (1) The gfs2_bmap that fsck uses to keep track of what block type has been discovered, and (2) The rgrp bitmap. Function gfs2_block_set is used to set the former and gfs2_set_bitmap @@ -188,8 +185,29 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) metadata when we're traversing the metadata with gfs2_next_rg_meta in func pass1(). If that happens, it will look at the block, say "hey this isn't metadata" and mark it incorrectly as an - invalid metadata block and free it. */ - gfs2_set_bitmap(ip->i_sbd, block, GFS2_BLKST_USED); + invalid metadata block and free it. Ordinarily, fsck will wait + until pass5 to sync (2) so that it agrees with (1). However, in + this case, it's better to do it upfront. The duplicate solving + code in pass1b.c is better at resolving metadata referencing a + data block than it is at resolving a data block referencing a + metadata block. */ + btype = gfs2_get_bitmap(ip->i_sbd, block, NULL); + if (btype != GFS2_BLKST_USED) { + const char *allocdesc[] = {"free space", "data", "unlinked", + "metadata", "reserved"}; + + errors_found++; + log_err( _("Block %llu (0x%llx) seems to be data, but is " + "marked as %s.\n", (unsigned long long)block, + (unsigned long long)block, allocdesc[btype])); + if(query(&opts, _("Okay to mark it as 'data'? (y/n)"))) { + errors_corrected++; + gfs2_set_bitmap(ip->i_sbd, block, GFS2_BLKST_USED); + log_err( _("The block was reassigned as data.\n")); + } else { + log_err( _("The invalid block was ignored.\n")); + } + } bc->data_count++; return error; } @@ -824,13 +842,22 @@ static int scan_meta(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, uint64_t block) { if (gfs2_check_meta(bh, 0)) { - log_info( _("Found invalid metadata at #%" PRIu64 " (0x%" PRIx64 ")\n"), - block, block); + errors_found++; + + log_info( _("Found invalid metadata at #%llu (0x%llx)\n"), + (unsigned long long)block, + (unsigned long long)block); if(gfs2_block_set(sdp, bl, block, gfs2_meta_inval)) { stack; return -1; } - gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); + if(query(&opts, _("Okay to free the invalid block? (y/n)"))) { + errors_corrected++; + gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); + log_err( _("The invalid block was freed.\n")); + } else { + log_err( _("The invalid block was ignored.\n")); + } return 0; } diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c index fd9c655..98e5729 100644 --- a/gfs2/libgfs2/fs_bits.c +++ b/gfs2/libgfs2/fs_bits.c @@ -144,3 +144,64 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) gfs2_rgrp_relse(rgd, updated); return 0; } + +/* + * fs_get_bitmap - get value of FS bitmap + * @sdp: super block + * @blkno: block number relative to file system + * + * This function gets the value of a bit of the + * file system bitmap. + * Possible state values for a block in the bitmap are: + * GFS_BLKST_FREE (0) + * GFS_BLKST_USED (1) + * GFS_BLKST_INVALID (2) + * GFS_BLKST_DINODE (3) + * + * Returns: state on success, -1 on error + */ +static int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, + struct rgrp_list *rgd) +{ + int i, val; + uint32_t rgrp_block; + struct gfs2_bitmap *bits = NULL; + unsigned int bit; + unsigned char *byte; + int local_rgd = 0; + + if(gfs2_check_range(sdp, blkno)) + return -1; + if(rgd == NULL) { + local_rgd = 1; + rgd = gfs2_blk2rgrpd(sdp, blkno); + } + if(rgd == NULL) + return -1; + if(gfs2_rgrp_read(sdp, rgd)) + return -1; + + rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0); + + for(i= 0; i < rgd->ri.ri_length; i++){ + bits = &(rgd->bits[i]); + if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY)){ + break; + } + } + + if(i >= rgd->ri.ri_length){ + gfs2_rgrp_relse(rgd, not_updated); + return -1; + } + + byte = (unsigned char *)(rgd->bh[i]->b_data + bits->bi_offset) + + (rgrp_block/GFS2_NBBY - bits->bi_start); + bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE; + + val = ((*byte >> bit) & GFS2_BIT_MASK); + if(local_rgd) + gfs2_rgrp_relse(rgd, not_updated); + + return val; +} diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index b64edd5..35560c8 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -426,6 +426,8 @@ extern uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal, extern int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno); /* functions with blk #'s that are file system relative */ +extern int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, + struct rgrp_list *rgd); extern int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state); /* fs_geometry.c */