This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cluster: STABLE3 - gfs2_edit savemeta needs to save freemeta blocks


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=3f4c655b0e025fbf591c8fef04c459d6d29f4cd8
Commit:        3f4c655b0e025fbf591c8fef04c459d6d29f4cd8
Parent:        9f5b1f4b4effa1bdcd2459a973e309566350804b
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Thu May 21 13:37:29 2009 -0500
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Thu May 21 14:07:06 2009 -0500

gfs2_edit savemeta needs to save freemeta blocks

bz 502056

The gfs2_edit savemeta function was not saving off
blocks of type 2, which correspond to "free metadata" in
gfs and "unlinked dinodes" in gfs2.  This turned out to be
a problem because if that metadata is restored and gfs is
tested against it, it resulted in metadata allocation
problems.  For example, gfs_grow may make the decision to
allocate a metadata block, and try to re-use a block that's
marked as "free metadata" in the gfs bitmap.  But since the
block hadn't been saved at "savemeta" time, the block was
never restored as metadata and therefore the metadata
header may be missing, so gfs-kernel withdrew with a file
system error.
---
 gfs2/edit/savemeta.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 5b72547..a463d74 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -443,6 +443,40 @@ static void get_journal_inode_blocks(void)
 	}
 }
 
+int next_rg_freemeta(struct rgrp_list *rgd, uint64_t *block, int first)
+{
+	struct gfs2_bitmap *bits = NULL;
+	uint32_t length = rgd->ri.ri_length;
+	uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0);
+	int i;
+
+	if(!first && (*block < rgd->ri.ri_data0)) {
+		log_err("next_rg_freemeta:  Start block is outside rgrp "
+			"bounds.\n");
+		exit(1);
+	}
+	for(i=0; i < length; i++){
+		bits = &rgd->bits[i];
+		if(blk < bits->bi_len*GFS2_NBBY)
+			break;
+		blk -= bits->bi_len*GFS2_NBBY;
+	}
+	for(; i < length; i++){
+		bits = &rgd->bits[i];
+		blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data +
+				  bits->bi_offset, bits->bi_len, blk,
+				  GFS2_BLKST_UNLINKED);
+		if(blk != BFITNOENT){
+			*block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
+			break;
+		}
+		blk=0;
+	}
+	if(i == length)
+		return -1;
+	return 0;
+}
+
 void savemeta(char *out_fn, int saveoption)
 {
 	int out_fd;
@@ -608,9 +642,9 @@ void savemeta(char *out_fn, int saveoption)
 			}
 			/* Save off the other metadata: inodes, etc. */
 			if (saveoption != 2) {
-				while (!gfs2_next_rg_meta(rgd, &block, first)) {
-					int blktype;
+				int blktype;
 
+				while (!gfs2_next_rg_meta(rgd, &block, first)) {
 					warm_fuzzy_stuff(block, FALSE, TRUE);
 					blktype = save_block(sbd.device_fd,
 							     out_fd, block);
@@ -618,6 +652,14 @@ void savemeta(char *out_fn, int saveoption)
 						save_inode_data(out_fd);
 					first = 0;
 				}
+				/* Save off the free/unlinked meta blocks too.
+				   If we don't, we may run into metadata
+				   allocation issues. */
+				while (!next_rg_freemeta(rgd, &block, first)) {
+					blktype = save_block(sbd.device_fd,
+							     out_fd, block);
+					first = 0;
+				}
 			}
 			gfs2_rgrp_relse(rgd, not_updated);
 		}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]