This is the mail archive of the
cluster-cvs@sourceware.org
mailing list for the cluster.
gfs2-utils: master - fsck.gfs2 writing bitmap when -n specified
- From: Bob Peterson <rpeterso at fedoraproject dot org>
- To: cluster-cvs-relay at redhat dot com
- Date: Fri, 19 Jun 2009 20:58:39 +0000 (UTC)
- Subject: gfs2-utils: master - fsck.gfs2 writing bitmap when -n specified
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=6f706bf2d51acdf0c00e93f3f55baf49e4f5114c
Commit: 6f706bf2d51acdf0c00e93f3f55baf49e4f5114c
Parent: 47b37cfb7beba33018d18d96eb754910112615a8
Author: Bob Peterson <rpeterso@redhat.com>
AuthorDate: Fri Jun 19 15:55:45 2009 -0500
Committer: Bob Peterson <rpeterso@redhat.com>
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 */