From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15979 invoked by alias); 21 May 2009 18:38:38 -0000 Received: (qmail 15972 invoked by alias); 21 May 2009 18:38:38 -0000 X-SWARE-Spam-Status: No, hits=-0.5 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_21,J_CHICKENPOX_23,J_CHICKENPOX_84,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_84,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 - gfs2_edit savemeta needs to save freemeta blocks 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: 764faccef5a7dc6988911502bcfcef806b1f83bb X-Git-Newrev: 938529b7cd58a007eadbefea716ecbdee5218050 From: Bob Peterson Message-Id: <20090521183721.0EC211201FA@lists.fedorahosted.org> Date: Thu, 21 May 2009 18:38: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/msg00378.txt.bz2 Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=938529b7cd58a007eadbefea716ecbdee5218050 Commit: 938529b7cd58a007eadbefea716ecbdee5218050 Parent: 764faccef5a7dc6988911502bcfcef806b1f83bb Author: Bob Peterson AuthorDate: Thu May 21 13:31:39 2009 -0500 Committer: Bob Peterson CommitterDate: Thu May 21 13:31:39 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); }