Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 35adedb8830cf948b43b86231991124b > files > 5

gfs2-utils-0.1.62-39.el5.src.rpm

commit 8bc98f2fad5ecf63e42bd44e93f5b5349c7f1253
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Fri Dec 4 10:40:54 2009 -0600

    Attach buffers to rgrp_list structs
    
    This patch attaches a buffer_head to every rgrp_list in memory.
    This greatly improves performance because it no longer needs to
    get and put the buffers for the rgrps all the time.  Since the
    buffers are linked to the rgrp list, they no longer need to be
    linked to each other, so it helps untangle the buffer_head mess.
    
    rhbz#455300

diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index f27b25f..e701169 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -166,29 +166,24 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 /*                   Fixes all unallocated metadata bitmap states (which are */
 /*                   valid in gfs1 but invalid in gfs2).                     */
 /* ------------------------------------------------------------------------- */
-static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rgd2,
-			    struct gfs2_buffer_head **rgbh)
+static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rg)
 {
 	uint32_t blk;
 	int x, y;
 	struct gfs2_rindex *ri;
 	unsigned char state;
 
-	ri = &rgd2->ri;
-	if (gfs2_compute_bitstructs(sdp, rgd2)) {
-		log_crit("gfs2_convert: Error converting bitmaps.\n");
-		exit(-1);
-	}
+	ri = &rg->ri;
 	for (blk = 0; blk < ri->ri_length; blk++) {
 		x = (blk) ? sizeof(struct gfs2_meta_header) :
 			sizeof(struct gfs2_rgrp);
 
 		for (; x < sdp->bsize; x++)
 			for (y = 0; y < GFS2_NBBY; y++) {
-				state = (rgbh[blk]->b_data[x] >>
+				state = (rg->bh[blk]->b_data[x] >>
 					 (GFS2_BIT_SIZE * y)) & 0x03;
 				if (state == 0x02) /* unallocated metadata state invalid */
-					rgbh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y));
+					rg->bh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y));
 			}
 	}
 }/* convert_bitmaps */
@@ -200,49 +195,34 @@ static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rgd2,
 static int convert_rgs(struct gfs2_sbd *sbp)
 {
 	struct rgrp_list *rgd;
-	struct gfs2_rgrp rg;
 	osi_list_t *tmp;
 	struct gfs1_rgrp *rgd1;
 	int rgs = 0;
-	struct gfs2_buffer_head **rgbh;
 
 	/* --------------------------------- */
 	/* Now convert its rgs into gfs2 rgs */
 	/* --------------------------------- */
 	osi_list_foreach(tmp, &sbp->rglist) {
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
-		if(!(rgbh = (struct gfs2_buffer_head **)
-		     malloc(rgd->ri.ri_length *
-			    sizeof(struct gfs2_buffer_head *))))
-			return -1;
-		if(!memset(rgbh, 0, rgd->ri.ri_length *
-			   sizeof(struct gfs2_buffer_head *))) {
-			free(rgbh);
-			return -1;
-		}
-
-		gfs2_rgrp_read(sbp, rgd, rgbh, &rg);
-		rgd1 = (struct gfs1_rgrp *)&rg; /* recast as gfs1 structure */
+		rgd1 = (struct gfs1_rgrp *)&rgd->rg; /* recast as gfs1 structure */
 		/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
 		/* convert from be to cpu. We must do it now. */
-		rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
-		rgd->rg_free = rg.rg_free;
+		rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
 		/* Zero it out so we don't add it again in case something breaks */
 		/* later on in the process and we have to re-run convert */
 		rgd1->rg_freemeta = 0;
 
 		sbp->blks_total += rgd->ri.ri_data;
-		sbp->blks_alloced += (rgd->ri.ri_data - rg.rg_free);
+		sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
 		sbp->dinodes_alloced += rgd1->rg_useddi;
-		convert_bitmaps(sbp, rgd, rgbh);
+		convert_bitmaps(sbp, rgd);
 		/* Write the updated rgrp to the gfs2 buffer */
-		gfs2_rgrp_out(&rg, rgbh[0]->b_data);
+		gfs2_rgrp_out(&rgd->rg, rgd->bh[0]->b_data);
 		rgs++;
 		if (rgs % 100 == 0) {
 			printf(".");
 			fflush(stdout);
 		}
-		free(rgbh);
 	}
 	return 0;
 }/* superblock_cvt */
@@ -991,8 +971,6 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
 	int first;
 	int error = 0;
 	int rgs_processed = 0;
-	struct gfs2_buffer_head **rgbh;
-	struct gfs2_rgrp rg;
 
 	log_notice("Converting inodes.\n");
 	sbp->md.next_inum = 1; /* starting inode numbering */
@@ -1006,20 +984,6 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
 		rgs_processed++;
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
 		first = 1;
-                if(!(rgbh = (struct gfs2_buffer_head **)
-                     malloc(rgd->ri.ri_length *
-                            sizeof(struct gfs2_buffer_head *))))
-                        return -1;
-                if(!memset(rgbh, 0, rgd->ri.ri_length *
-                           sizeof(struct gfs2_buffer_head *))) {
-			free(rgbh);
-                        return -1;
-		}
-		if (gfs2_rgrp_read(sbp, rgd, rgbh, &rg)) {
-			log_crit("Unable to read rgrp.\n");
-			free(rgbh);
-			return -1;
-		}
 		while (1) {    /* for all inodes in the resource group */
 			gettimeofday(&tv, NULL);
 			/* Put out a warm, fuzzy message every second so the customer */
@@ -1062,21 +1026,19 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
 						sizeof(struct gfs2_rgrp);
 					/* if it's on this page */
 					if (buf_offset + bitmap_byte < sbp->bsize) {
-						rgbh[blk]->b_data[buf_offset + bitmap_byte] &=
+						rgd->bh[blk]->b_data[buf_offset + bitmap_byte] &=
 							~(0x03 << (GFS2_BIT_SIZE * byte_bit));
-						rgbh[blk]->b_data[buf_offset + bitmap_byte] |=
+						rgd->bh[blk]->b_data[buf_offset + bitmap_byte] |=
 							(0x01 << (GFS2_BIT_SIZE * byte_bit));
 						break;
 					}
 					bitmap_byte -= (sbp->bsize - buf_offset);
-					bmodified(bh);
+					bmodified(rgd->bh[blk]);
 				}
 			}
 			brelse(bh);
 			first = 0;
 		} /* while 1 */
-		gfs2_rgrp_relse(rgd, rgbh);
-		free(rgbh);
 	} /* for all rgs */
 	log_notice("\r%" PRIu64" inodes from %d rgs converted.",
 		   sbp->md.next_inum, rgs_processed);
@@ -1622,8 +1584,6 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
 	struct rgrp_list *rgd, *rgdhigh;
 	osi_list_t *tmp;
 	struct gfs2_meta_header mh;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
 
 	mh.mh_magic = GFS2_MAGIC;
 	mh.mh_type = GFS2_METATYPE_RB;
@@ -1663,11 +1623,11 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
 		}
 		memset(rgd, 0, sizeof(struct rgrp_list));
 		size = jndx->ji_nsegment * be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size);
-		rg.rg_header.mh_magic = GFS2_MAGIC;
-		rg.rg_header.mh_type = GFS2_METATYPE_RG;
-		rg.rg_header.mh_format = GFS2_FORMAT_RG;
-		rg.rg_flags = 0;
-		rg.rg_dinodes = 0;
+		rgd->rg.rg_header.mh_magic = GFS2_MAGIC;
+		rgd->rg.rg_header.mh_type = GFS2_METATYPE_RG;
+		rgd->rg.rg_header.mh_format = GFS2_FORMAT_RG;
+		rgd->rg.rg_flags = 0;
+		rgd->rg.rg_dinodes = 0;
 
 		rgd->ri.ri_addr = jndx->ji_addr; /* new rg addr becomes ji addr */
 		rgd->ri.ri_length = rgrp_length(size, sdp); /* aka bitblocks */
@@ -1678,31 +1638,36 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
 		while (rgd->ri.ri_data & 0x03)
 			rgd->ri.ri_data--;
 		sdp->blks_total += rgd->ri.ri_data; /* For statfs file update */
-		rg.rg_free = rgd->ri.ri_data;
+		rgd->rg.rg_free = rgd->ri.ri_data;
 		rgd->ri.ri_bitbytes = rgd->ri.ri_data / GFS2_NBBY;
 
-		if(!(rgbh = (struct gfs2_buffer_head **)
+		if(!(rgd->bh = (struct gfs2_buffer_head **)
 		     malloc(rgd->ri.ri_length *
 			    sizeof(struct gfs2_buffer_head *))))
 			return -1;
-		if(!memset(rgbh, 0, rgd->ri.ri_length *
+		if(!memset(rgd->bh, 0, rgd->ri.ri_length *
 			   sizeof(struct gfs2_buffer_head *))) {
-			free(rgbh);
+			free(rgd->bh);
 			return -1;
 		}
-
-		convert_bitmaps(sdp, rgd, rgbh);
 		for (x = 0; x < rgd->ri.ri_length; x++) {
-			rgbh[x]->b_count++;
+			rgd->bh[x] = bget(&sdp->buf_list, rgd->ri.ri_addr + x);
+			memset(rgd->bh[x]->b_data, 0, sdp->bsize);
+		}
+		if (gfs2_compute_bitstructs(sdp, rgd)) {
+			log_crit("gfs2_convert: Error converting bitmaps.\n");
+			exit(-1);
+		}
+		convert_bitmaps(sdp, rgd);
+		for (x = 0; x < rgd->ri.ri_length; x++) {
 			if (x)
-				gfs2_meta_header_out(&mh, rgbh[x]->b_data);
+				gfs2_meta_header_out(&mh, rgd->bh[x]->b_data);
 			else
-				gfs2_rgrp_out(&rg, rgbh[x]->b_data);
+				gfs2_rgrp_out(&rgd->rg, rgd->bh[x]->b_data);
 		}
 		/* Add the new gfs2 rg to our list: We'll output the rg index later. */
 		osi_list_add_prev((osi_list_t *)&rgd->list,
 						  (osi_list_t *)&sdp->rglist);
-		free(rgbh);
 	} /* for each journal */
 	return error;
 }/* journ_space_to_rg */
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index ef0bc50..a0b9b81 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -580,9 +580,11 @@ int display_block_type(const char *lpBuffer, int from_restore)
 		struct rgrp_list *rgd;
 
 		rgd = gfs2_blk2rgrpd(&sbd, block);
-		if (rgd)
+		if (rgd) {
+			gfs2_rgrp_read(&sbd, rgd);
 			type = gfs2_get_bitmap(&sbd, block, rgd);
-		else
+			gfs2_rgrp_relse(rgd);
+		} else
 			type = 4;
 		screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
 		if (!screen_chunk_size)
@@ -1707,7 +1709,7 @@ static int display_extended(void)
 /* ------------------------------------------------------------------------ */
 static void read_superblock(int fd)
 {
-	int count, bitmap_blocks = 0;
+	int count;
 
 	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
@@ -1759,8 +1761,7 @@ static void read_superblock(int fd)
 		sbd.md.riinode = gfs2_load_inode(&sbd,
 						 sbd1->sb_rindex_di.no_addr);
 		sbd.fssize = sbd.device.length;
-		gfs1_rindex_read(&sbd, fd, &count, &bitmap_blocks);
-		/*gfs1_ri_update(&sbd, 0, &count, 1);*/
+		gfs1_rindex_read(&sbd, 0, &count);
 	} else {
 		sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs2_meta_header)) /
 			sizeof(uint64_t);
@@ -1770,8 +1771,7 @@ static void read_superblock(int fd)
 					    sbd.sd_sb.sb_master_dir.no_addr);
 		gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode);
 		sbd.fssize = sbd.device.length;
-		rindex_read(&sbd, fd, &count, &bitmap_blocks);
-		/*ri_update(&sbd, 0, &count);*/
+		rindex_read(&sbd, 0, &count);
 	}
 
 }
@@ -2528,7 +2528,9 @@ static void find_change_block_alloc(int *newval)
 		} else {
 			rgd = gfs2_blk2rgrpd(&sbd, ablock);
 			if (rgd) {
+				gfs2_rgrp_read(&sbd, rgd);
 				type = gfs2_get_bitmap(&sbd, ablock, rgd);
+				gfs2_rgrp_relse(rgd);
 				printf("%d (%s)\n", type, allocdesc[gfs1][type]);
 			} else {
 				gfs2_rgrp_free(&sbd.rglist);
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 51ea37a..3a34c96 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -497,8 +497,6 @@ void savemeta(char *out_fn, int saveoption)
 	int rgcount;
 	uint64_t jindex_block;
 	struct gfs2_buffer_head *bh;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
 
 	slow = (saveoption == 1);
 	sbd.md.journals = 1;
@@ -622,16 +620,7 @@ void savemeta(char *out_fn, int saveoption)
 			int i, first;
 
 			rgd = osi_list_entry(tmp, struct rgrp_list, list);
-			if(!(rgbh = (struct gfs2_buffer_head **)
-			     malloc(rgd->ri.ri_length *
-				    sizeof(struct gfs2_buffer_head *))))
-				break;
-			if(!memset(rgbh, 0, rgd->ri.ri_length *
-				   sizeof(struct gfs2_buffer_head *))) {
-				free(rgbh);
-				break;
-			}
-			slow = gfs2_rgrp_read(&sbd, rgd, rgbh, &rg);
+			slow = gfs2_rgrp_read(&sbd, rgd);
 			if (slow)
 				continue;
 			log_debug("RG at %"PRIu64" is %u long\n",
@@ -653,8 +642,7 @@ void savemeta(char *out_fn, int saveoption)
 			if (saveoption != 2) {
 				int blktype;
 
-				while (!gfs2_next_rg_meta(&sbd, rgd, &block,
-							  first)) {
+				while (!gfs2_next_rg_meta(rgd, &block, first)){
 					warm_fuzzy_stuff(block, FALSE, TRUE);
 					blktype = save_block(sbd.device_fd,
 							     out_fd, block);
@@ -672,8 +660,7 @@ void savemeta(char *out_fn, int saveoption)
 					first = 0;
 				}
 			}
-			gfs2_rgrp_relse(rgd, rgbh);
-			free(rgbh);
+			gfs2_rgrp_relse(rgd);
 		}
 	}
 	if (slow) {
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 5985919..d82313b 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -87,17 +87,7 @@ static void empty_super_block(struct gfs2_sbd *sdp)
 	uint32_t i;
 
 	log_info( _("Freeing buffers.\n"));
-	while(!osi_list_empty(&sdp->rglist)){
-		struct rgrp_list *rgd;
-
-		rgd = osi_list_entry(sdp->rglist.next, struct rgrp_list, list);
-		log_debug( _("Deleting rgd for 0x%llx:  rgd=0x%p bits=0x%p\n"),
-			  (unsigned long long)rgd->ri.ri_addr, rgd, rgd->bits);
-		osi_list_del(&rgd->list);
-		if(rgd->bits)
-			free(rgd->bits);
-		free(rgd);
-	}
+	gfs2_rgrp_free(&sdp->rglist);
 
 	for(i = 0; i < FSCK_HASH_SIZE; i++) {
 		while(!osi_list_empty(&inode_hash[i])) {
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 841d351..953c2dc 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -307,11 +307,11 @@ void check_statfs(struct gfs2_sbd *sdp)
 			log_err( _("Error: can't allocate memory to check statfs.\n"));
 			return;
 		}
-		gfs2_rgrp_read(sdp, rgd, rgbh, &rg);
+		gfs2_rgrp_read(sdp, rgd);
 		sdp->blks_total += ri->ri_data;
 		sdp->blks_alloced += (ri->ri_data - rg.rg_free);
 		sdp->dinodes_alloced += rg.rg_dinodes;
-		gfs2_rgrp_relse(rgd, rgbh);
+		gfs2_rgrp_relse(rgd);
 		free(rgbh);
 	}
 
@@ -341,7 +341,7 @@ void check_statfs(struct gfs2_sbd *sdp)
 		sdp->dinodes_alloced, sdp->dinodes_alloced);
 
 	errors_found++;
-	if (!query(&opts, _("Okay to fix the master statfs file? (y/n)"))) {
+	if (!query( _("Okay to fix the master statfs file? (y/n)"))) {
 		log_err( _("The statfs file was not fixed.\n"));
 		return;
 	}
@@ -358,6 +358,8 @@ int main(int argc, char **argv)
 	int j;
 	int error = 0;
 	int all_clean = 0;
+	osi_list_t *tmp;
+	struct rgrp_list *rgd;
 
 	setlocale(LC_ALL, "");
 	textdomain("gfs2-utils");
@@ -494,6 +496,11 @@ int main(int argc, char **argv)
 	if (!opts.no && errors_corrected)
 		log_notice( _("Writing changes to disk\n"));
 
+	for (tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next) {
+		rgd = osi_list_entry(tmp, struct rgrp_list, list);
+		gfs2_rgrp_relse(rgd);
+	}
+
 	bsync(&sbp->buf_list);
 	destroy(sbp);
 	log_notice( _("gfs2_fsck complete    \n"));
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index f61164c..bbf2e83 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -967,8 +967,6 @@ int pass1(struct gfs2_sbd *sbp)
 	uint64_t blk_count;
 	uint64_t offset;
 	uint64_t rg_count = 0;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
 
 	/* FIXME: In the gfs fsck, we had to mark things like the
 	 * journals and indices and such as 'other_meta' - in gfs2,
@@ -991,29 +989,10 @@ int pass1(struct gfs2_sbd *sbp)
 		log_info( _("Checking metadata in Resource Group #%" PRIu64 "\n"),
 				 rg_count);
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
-		if(!(rgbh = (struct gfs2_buffer_head **)
-		     malloc(rgd->ri.ri_length *
-			    sizeof(struct gfs2_buffer_head *))))
-			return FSCK_ERROR;
-		if(!memset(rgbh, 0, rgd->ri.ri_length *
-			   sizeof(struct gfs2_buffer_head *))) {
-			free(rgbh);
-			return FSCK_ERROR;
-		}
-		if(gfs2_rgrp_read(sbp, rgd, rgbh, &rg)){
-			stack;
-			free(rgbh);
-			return FSCK_ERROR;
-		}
-		log_debug( _("RG at %llu (0x%llx) is %u long\n"),
-			  (unsigned long long)rgd->ri.ri_addr,
-			  (unsigned long long)rgd->ri.ri_addr,
-			  rgd->ri.ri_length);
 		for (i = 0; i < rgd->ri.ri_length; i++) {
 			if(gfs2_block_set(sbp, bl, rgd->ri.ri_addr + i,
 					  gfs2_meta_other)){
 				stack;
-				free(rgbh);
 				return FSCK_ERROR;
 			}
 		}
@@ -1024,14 +1003,11 @@ int pass1(struct gfs2_sbd *sbp)
 
 		while (1) {
 			/* "block" is relative to the entire file system */
-			if (gfs2_next_rg_meta(sbp, rgd, &block, first))
+			if (gfs2_next_rg_meta(rgd, &block, first))
 				break;
 			warm_fuzzy_stuff(block);
-			if (fsck_abort) { /* if asked to abort */
-				gfs2_rgrp_relse(rgd, rgbh);
-				free(rgbh);
+			if (fsck_abort) /* if asked to abort */
 				return FSCK_OK;
-			}
 			if (skip_this_pass) {
 				printf( _("Skipping pass 1 is not a good idea.\n"));
 				skip_this_pass = FALSE;
@@ -1042,15 +1018,11 @@ int pass1(struct gfs2_sbd *sbp)
 			if (scan_meta(sbp, bh, block)) {
 				stack;
 				brelse(bh);
-				gfs2_rgrp_relse(rgd, rgbh);
-				free(rgbh);
 				return FSCK_ERROR;
 			}
 			brelse(bh);
 			first = 0;
 		}
-		gfs2_rgrp_relse(rgd, rgbh);
-		free(rgbh);
 	}
 	return FSCK_OK;
 }
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index f36eb7d..dae2c66 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -158,8 +158,7 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b
 }
 
 static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
-			uint32_t *count, struct gfs2_buffer_head **rgbh,
-			struct gfs2_rgrp *rg)
+			uint32_t *count)
 {
 	uint32_t i;
 	struct gfs2_bitmap *bits;
@@ -170,26 +169,26 @@ static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
 		bits = &rgp->bits[i];
 
 		/* update the bitmaps */
-		check_block_status(sbp, rgbh[i]->b_data + bits->bi_offset,
+		check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset,
 						   bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
 		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
 			return;
 	}
 
 	/* actually adjust counters and write out to disk */
-	if(rgp->rg_free != count[0]) {
+	if(rgp->rg.rg_free != count[0]) {
 		log_err( _("RG #%llu (0x%llx) free count inconsistent: "
 			"is %u should be %u\n"),
 			(unsigned long long)rgp->ri.ri_addr,
 			(unsigned long long)rgp->ri.ri_addr,
-			rgp->rg_free, count[0]);
-		rgp->rg_free = count[0];
+			rgp->rg.rg_free, count[0]);
+		rgp->rg.rg_free = count[0];
 		update = 1;
 	}
-	if(rg->rg_dinodes != count[1]) {
+	if(rgp->rg.rg_dinodes != count[1]) {
 		log_err( _("Inode count inconsistent: is %u should be %u\n"),
-				rg->rg_dinodes, count[1]);
-		rg->rg_dinodes = count[1];
+				rgp->rg.rg_dinodes, count[1]);
+		rgp->rg.rg_dinodes = count[1];
 		update = 1;
 	}
 	if((rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
@@ -203,7 +202,7 @@ static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
 		if(query( _("Update resource group counts? (y/n) "))) {
 			log_warn( _("Resource group counts updated\n"));
 			/* write out the rgrp */
-			gfs2_rgrp_out(rg, rgbh[0]->b_data);
+			gfs2_rgrp_out(&rgp->rg, rgp->bh[0]->b_data);
 		} else
 			log_err( _("Resource group counts left inconsistent\n"));
 	}
@@ -218,11 +217,9 @@ static void update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
 int pass5(struct gfs2_sbd *sbp)
 {
 	osi_list_t *tmp;
-	struct rgrp_list *rgd = NULL;
+	struct rgrp_list *rgp = NULL;
 	uint32_t count[3];
 	uint64_t rg_count = 0;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
 
 	/* Reconcile RG bitmaps with fsck bitmap */
 	for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
@@ -230,27 +227,11 @@ int pass5(struct gfs2_sbd *sbp)
 			return FSCK_OK;
 		log_info( _("Verifying Resource Group #%" PRIu64 "\n"), rg_count);
 		memset(count, 0, sizeof(count));
-		rgd = osi_list_entry(tmp, struct rgrp_list, list);
+		rgp = osi_list_entry(tmp, struct rgrp_list, list);
 
-		if(!(rgbh = (struct gfs2_buffer_head **)
-		     malloc(rgd->ri.ri_length *
-			    sizeof(struct gfs2_buffer_head *))))
-			return FSCK_ERROR;
-		if(!memset(rgbh, 0, rgd->ri.ri_length *
-			   sizeof(struct gfs2_buffer_head *))) {
-			free(rgbh);
-			return FSCK_ERROR;
-		}
-		if(gfs2_rgrp_read(sbp, rgd, rgbh, &rg)){
-			stack;
-			free(rgbh);
-			return FSCK_ERROR;
-		}
 		rg_count++;
 		/* Compare the bitmaps and report the differences */
-		update_rgrp(sbp, rgd, count, rgbh, &rg);
-		gfs2_rgrp_relse(rgd, rgbh);
-		free(rgbh);
+		update_rgrp(sbp, rgp, count);
 	}
 	/* Fix up superblock info based on this - don't think there's
 	 * anything to do here... */
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index 06603b1..65080a2 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -378,36 +378,35 @@ static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list,
  * rewrite_rg_block - rewrite ("fix") a buffer with rg or bitmap data
  * returns: 0 if the rg was repaired, otherwise 1
  */
-static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-		     uint64_t errblock, struct gfs2_buffer_head **rgbh,
-		     struct gfs2_rgrp *rg)
+static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
+		     uint64_t errblock)
 {
-	int x = errblock - rgd->ri.ri_addr;
+	int x = errblock - rg->ri.ri_addr;
 
 	log_err( _("Block #%"PRIu64" (0x%" PRIx64") (%d of %d) is neither"
 		" GFS2_METATYPE_RB nor GFS2_METATYPE_RG.\n"),
-		rgbh[x]->b_blocknr, rgbh[x]->b_blocknr,
-		(int)x+1, (int)rgd->ri.ri_length);
-	if (query( _("Fix the RG? (y/n)"))) {
+		rg->bh[x]->b_blocknr, rg->bh[x]->b_blocknr,
+		(int)x+1, (int)rg->ri.ri_length);
+	if (query( _("Fix the Resource Group? (y/n)"))) {
 		log_err( _("Attempting to repair the RG.\n"));
-		rgbh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x);
+		rg->bh[x] = bread(&sdp->buf_list, rg->ri.ri_addr + x);
 		if (x) {
 			struct gfs2_meta_header mh;
 
 			mh.mh_magic = GFS2_MAGIC;
 			mh.mh_type = GFS2_METATYPE_RB;
 			mh.mh_format = GFS2_FORMAT_RB;
-			gfs2_meta_header_out(&mh, rgbh[x]->b_data);
+			gfs2_meta_header_out(&mh, rg->bh[x]->b_data);
 		} else {
-			memset(rg, 0, sizeof(struct gfs2_rgrp));
-			rg->rg_header.mh_magic = GFS2_MAGIC;
-			rg->rg_header.mh_type = GFS2_METATYPE_RG;
-			rg->rg_header.mh_format = GFS2_FORMAT_RG;
-			rg->rg_free = rgd->ri.ri_data;
-			gfs2_rgrp_out(rg, rgbh[x]->b_data);
+			memset(&rg->rg, 0, sizeof(struct gfs2_rgrp));
+			rg->rg.rg_header.mh_magic = GFS2_MAGIC;
+			rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
+			rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
+			rg->rg.rg_free = rg->ri.ri_data;
+			gfs2_rgrp_out(&rg->rg, rg->bh[x]->b_data);
 		}
-		bmodified(rgbh[x]);
-		brelse(rgbh[x]);
+		bmodified(rg->bh[x]);
+		brelse(rg->bh[x]);
 		return 0;
 	}
 	return 1;
@@ -428,7 +427,6 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count)
 	int calc_rg_count = 0, rgcount_from_index, rg;
 	osi_list_t *exp, *act; /* expected, actual */
 	struct gfs2_rindex buf;
-	int bitmap_blocks;
 
 	if (trust_lvl == blind_faith)
 		return 0;
@@ -453,7 +451,7 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count)
 	}
 	/* Read in the rindex */
 	osi_list_init(&sdp->rglist); /* Just to be safe */
-	rindex_read(sdp, 0, &rgcount_from_index, &bitmap_blocks);
+	rindex_read(sdp, 0, &rgcount_from_index);
 	if (sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex)) {
 		log_warn( _("WARNING: rindex file is corrupt.\n"));
 		gfs2_rgrp_free(&expected_rglist);
@@ -555,41 +553,22 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count)
 		struct rgrp_list *rgd;
 		uint64_t prev_err = 0, errblock;
 		int i;
-		struct gfs2_rgrp rgrp;
-		struct gfs2_buffer_head **rgbh;
 
 		/* Now we try repeatedly to read in the rg.  For every block */
 		/* we encounter that has errors, repair it and try again.    */
 		i = 0;
 		do {
 			rgd = osi_list_entry(act, struct rgrp_list, list);
-
-			if(!(rgbh = (struct gfs2_buffer_head **)
-			     malloc(rgd->ri.ri_length *
-				    sizeof(struct gfs2_buffer_head *))))
-				return -1;
-			if(!memset(rgbh, 0, bitmap_blocks *
-				   sizeof(struct gfs2_buffer_head *))) {
-				free(rgbh);
-				return -1;
-			}
-
-			errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rgrp);
+			errblock = gfs2_rgrp_read(sdp, rgd);
 			if (errblock) {
-				if (errblock == prev_err) {
-					free(rgbh);
+				if (errblock == prev_err)
 					break;
-				}
 				prev_err = errblock;
-				rewrite_rg_block(sdp, rgd, errblock, rgbh,
-						 &rgrp);
-			}
-			else {
-				gfs2_rgrp_relse(rgd, rgbh);
-				free(rgbh);
+				rewrite_rg_block(sdp, rgd, errblock);
+			} else {
+				gfs2_rgrp_relse(rgd);
 				break;
 			}
-			free(rgbh);
 			i++;
 		} while (i < rgd->ri.ri_length);
 	}
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
index 73499c8..9dc34c8 100644
--- a/gfs2/libgfs2/fs_bits.c
+++ b/gfs2/libgfs2/fs_bits.c
@@ -172,8 +172,6 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
 	struct rgrp_list *rgd;
 	unsigned char *byte, cur_state;
 	unsigned int bit;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
 
 	/* FIXME: should GFS2_BLKST_INVALID be allowed */
 	if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE))
@@ -184,20 +182,6 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
 	if(!rgd)
 		return -1;
 
-	if(!(rgbh = (struct gfs2_buffer_head **)
-	     malloc(rgd->ri.ri_length *
-		    sizeof(struct gfs2_buffer_head *))))
-		return -1;
-	if(!memset(rgbh, 0, rgd->ri.ri_length *
-		   sizeof(struct gfs2_buffer_head *))) {
-		free(rgbh);
-		return -1;
-	}
-
-	if(gfs2_rgrp_read(sdp, rgd, rgbh, &rg)) {
-		free(rgbh);
-		return -1;
-	}
 	rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0);
 	for(buf= 0; buf < rgd->ri.ri_length; buf++){
 		bits = &(rgd->bits[buf]);
@@ -205,7 +189,7 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
 			break;
 	}
 
-	byte = (unsigned char *)(rgbh[buf]->b_data + bits->bi_offset) +
+	byte = (unsigned char *)(rgd->bh[buf]->b_data + bits->bi_offset) +
 		(rgrp_block/GFS2_NBBY - bits->bi_start);
 	bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
 
@@ -213,9 +197,7 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
 	*byte ^= cur_state << bit;
 	*byte |= state << bit;
 
-	bmodified(rgbh[buf]);
-	gfs2_rgrp_relse(rgd, rgbh);
-	free(rgbh);
+	bmodified(rgd->bh[buf]);
 	return 0;
 }
 
@@ -242,51 +224,28 @@ int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
 	struct gfs2_bitmap	*bits = NULL;
 	unsigned int  bit;
 	unsigned char *byte;
-	int local_rgd = 0;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
-	int bitmap_blocks = rgd->length;
 
-	if(gfs2_check_range(sdp, blkno))
-		return -1;
-	if(rgd == NULL) {
-		local_rgd = 1;
+	if (rgd == NULL) {
 		rgd = gfs2_blk2rgrpd(sdp, blkno);
-	}
-	if(rgd == NULL)
-		return -1;
-	if(!(rgbh = (struct gfs2_buffer_head **)
-	     malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *))))
-		return -1;
-	if(!memset(rgbh, 0, bitmap_blocks *
-		   sizeof(struct gfs2_buffer_head *))) {
-		free(rgbh);
-		return -1;
+		if(rgd == NULL)
+			return -1;
 	}
 
-	if(gfs2_rgrp_read(sdp, rgd, rgbh, &rg))
-		return -1;
-
 	rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0);
 
-	for(i= 0; i < rgd->ri.ri_length; i++){
+	for (i = 0; i < rgd->ri.ri_length; i++) {
 		bits = &(rgd->bits[i]);
-		if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY)){
+		if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
 			break;
-		}
 	}
 
-	if(i >= rgd->ri.ri_length){
-		gfs2_rgrp_relse(rgd, rgbh);
+	if (i >= rgd->ri.ri_length)
 		return -1;
-	}
-
-	byte = (unsigned char *)(rgbh[i]->b_data + bits->bi_offset) +
+	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, rgbh);
+
 	return val;
 }
diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c
index 0c8c169..aa62edf 100644
--- a/gfs2/libgfs2/fs_geometry.c
+++ b/gfs2/libgfs2/fs_geometry.c
@@ -219,7 +219,6 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write)
 		rg.rg_header.mh_type = GFS2_METATYPE_RG;
 		rg.rg_header.mh_format = GFS2_FORMAT_RG;
 		rg.rg_free = rgblocks;
-		rl->rg_free = rgblocks;
 
 		if (do_write) {
 			for (x = 0; x < bitblocks; x++) {
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 63c190c..48ad90d 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -55,17 +55,16 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
 	osi_list_t *tmp, *head;
 	struct rgrp_list *rl = NULL;
 	struct gfs2_rindex *ri;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh;
+	struct gfs2_rgrp *rg;
 	unsigned int block, bn = 0, x = 0, y = 0;
 	unsigned int state;
+	struct gfs2_buffer_head *bh;
 
 	memset(&rg, 0, sizeof(rg));
-	for (head = &sdp->rglist, tmp = head->next;
-	     tmp != head;
+	for (head = &sdp->rglist, tmp = head->next; tmp != head;
 	     tmp = tmp->next) {
 		rl = osi_list_entry(tmp, struct rgrp_list, list);
-		if (rl->rg_free)
+		if (rl->rg.rg_free)
 			break;
 	}
 
@@ -73,43 +72,29 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
 		die("out of space\n");
 
 	ri = &rl->ri;
-
-	if(!(rgbh = (struct gfs2_buffer_head **)
-	     malloc(rl->ri.ri_length *
-		    sizeof(struct gfs2_buffer_head *))))
-		return -1;
-	if(!memset(rgbh, 0, rl->ri.ri_length *
-		   sizeof(struct gfs2_buffer_head *))) {
-		free(rgbh);
-		return -1;
-	}
+	rg = &rl->rg;
 
 	for (block = 0; block < ri->ri_length; block++) {
-		rgbh[block] = bread(&sdp->buf_list, ri->ri_addr + block);
+		bh = rl->bh[block];
 		x = (block) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp);
 
-		if (!block)
-			gfs2_rgrp_in(&rg, rgbh[0]->b_data);
 		for (; x < sdp->bsize; x++)
 			for (y = 0; y < GFS2_NBBY; y++) {
-				state = (rgbh[block]->b_data[x] >>
-					 (GFS2_BIT_SIZE * y)) & 0x03;
+				state = (bh->b_data[x] >> (GFS2_BIT_SIZE * y)) & 0x03;
 				if (state == GFS2_BLKST_FREE)
 					goto found;
 				bn++;
 			}
-
-		brelse(rgbh[block]);
 	}
 
 	die("allocation is broken (1): %"PRIu64" %u\n",
-	    (uint64_t)rl->ri.ri_addr, rl->rg_free);
+	    (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
 
  found:
 	if (bn >= ri->ri_bitbytes * GFS2_NBBY)
 		die("allocation is broken (2): %u %u %"PRIu64" %u\n",
 		    bn, ri->ri_bitbytes * GFS2_NBBY,
-		    (uint64_t)rl->ri.ri_addr, rl->rg_free);
+		    (uint64_t)rl->ri.ri_addr, rl->rg.rg_free);
 
 	switch (type) {
 	case DATA:
@@ -118,27 +103,20 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
 		break;
 	case DINODE:
 		state = GFS2_BLKST_DINODE;
-		rg.rg_dinodes++;
+		rg->rg_dinodes++;
 		break;
 	default:
 		die("bad state\n");
 	}
 
-	rgbh[block]->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y));
-	rgbh[block]->b_data[x] |= state << (GFS2_BIT_SIZE * y);
-	rg.rg_free--;
-	rl->rg_free--;
-
-	bmodified(rgbh[block]);
-	brelse(rgbh[block]);
+	bh->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y));
+	bh->b_data[x] |= state << (GFS2_BIT_SIZE * y);
+	rg->rg_free--;
 
-	rgbh[0] = bread(&sdp->buf_list, ri->ri_addr);
-	gfs2_rgrp_out(&rg, rgbh[0]->b_data);
-	bmodified(rgbh[0]);
-	brelse(rgbh[0]);
+	bmodified(bh);
+	gfs2_rgrp_out(rg, rl->bh[0]->b_data);
 
 	sdp->blks_alloced++;
-	free(rgbh);
 	return ri->ri_data0 + bn;
 }
 
@@ -1597,21 +1575,16 @@ int gfs2_lookupi(struct gfs2_inode *dip, const char *filename, int len,
  */
 void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block)
 {
-	struct gfs2_buffer_head *bh;
 	struct rgrp_list *rgd;
-	struct gfs2_rgrp rg;
 
-	gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE);
 	/* Adjust the free space count for the freed block */
 	rgd = gfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */
-	bh = bget(&sdp->buf_list, rgd->ri.ri_addr); /* get the rg buffer */
-	gfs2_rgrp_in(&rg, bh->b_data); /* back to the buffer */
-	rg.rg_free++; /* adjust the free count */
-	rgd->rg_free++;
-	gfs2_rgrp_out(&rg, bh->b_data); /* back to the buffer */
-	bmodified(bh);
-	brelse(bh); /* release the buffer */
-	sdp->blks_alloced--;
+	if (rgd) {
+		gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE);
+		rgd->rg.rg_free++; /* adjust the free count */
+		gfs2_rgrp_out(&rgd->rg, rgd->bh[0]->b_data); /* back to the buffer */
+		sdp->blks_alloced--;
+	}
 }
 
 /**
@@ -1628,7 +1601,6 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock)
 	uint32_t height;
 	osi_list_t metalist[GFS2_MAX_META_HEIGHT];
 	osi_list_t *cur_list, *next_list, *tmp;
-	struct gfs2_rgrp rg;
 
 	for (h = 0; h < GFS2_MAX_META_HEIGHT; h++)
 		osi_list_init(&metalist[h]);
@@ -1673,14 +1645,9 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock)
 	sdp->blks_alloced--;
 	/* Now we have to adjust the rg freespace count and inode count: */
 	rgd = gfs2_blk2rgrpd(sdp, diblock);
-	bh = bread(&sdp->buf_list, rgd->ri.ri_addr); /* get the buffer */
-	gfs2_rgrp_in(&rg, bh->b_data);
-	rg.rg_free++;
-	rgd->rg_free++;
-	rg.rg_dinodes--; /* one less inode in use */
-	gfs2_rgrp_out(&rg, bh->b_data);
-	bmodified(bh);
-	brelse(bh); /* release the buffer */
+	rgd->rg.rg_free++;
+	rgd->rg.rg_dinodes--; /* one less inode in use */
+	gfs2_rgrp_out(&rgd->rg, rgd->bh[0]->b_data);
 	sdp->dinodes_alloced--;
 	return 0;
 }
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
index 428ba70..0f59669 100644
--- a/gfs2/libgfs2/gfs1.c
+++ b/gfs2/libgfs2/gfs1.c
@@ -229,8 +229,7 @@ int gfs1_readi(struct gfs2_inode *ip, void *bufin,
  *
  * Returns: 0 on success, -1 on failure
  */
-int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
-		     int *bitmap_blocks)
+int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
 {
 	unsigned int rg;
 	int error;
@@ -240,7 +239,6 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
 
 	*count1 = 0;
 	prev_rgd = NULL;
-	*bitmap_blocks = 0;
 	for (rg = 0; ; rg++) {
 		if (fd > 0)
 			error = read(fd, &buf, sizeof(struct gfs2_rindex));
@@ -263,8 +261,6 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
 
 		gfs2_rindex_in(&rgd->ri, (char *)&buf);
 
-		if (rgd->ri.ri_length > *bitmap_blocks)
-			*bitmap_blocks = rgd->ri.ri_length;
 		rgd->start = rgd->ri.ri_addr;
 		if (prev_rgd) {
 			prev_length = rgd->start - prev_rgd->start;
@@ -295,48 +291,37 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
 int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet)
 {
 	struct rgrp_list *rgd;
+	struct gfs2_rindex *ri;
 	osi_list_t *tmp;
 	int count1 = 0, count2 = 0;
 	uint64_t errblock = 0;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh = NULL;
-	int bitmap_blocks;
+	uint64_t rmax = 0;
 
-	if (gfs1_rindex_read(sdp, fd, &count1, &bitmap_blocks))
+	if (gfs1_rindex_read(sdp, fd, &count1))
 	    goto fail;
-
-	if(!(rgbh = (struct gfs2_buffer_head **)
-	     malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *))))
-		return -1;
-	if(!memset(rgbh, 0, bitmap_blocks *
-		   sizeof(struct gfs2_buffer_head *))) {
-		free(rgbh);
-		return -1;
-	}
 	for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
-		errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rg);
-		if (errblock) {
-			free(rgbh);
+		errblock = gfs2_rgrp_read(sdp, rgd);
+		if (errblock)
 			return errblock;
-		}
 		count2++;
 		if (!quiet && count2 % 100 == 0) {
 			printf(".");
 			fflush(stdout);
 		}
+		ri = &rgd->ri;
+		if (ri->ri_data0 + ri->ri_data - 1 > rmax)
+			rmax = ri->ri_data0 + ri->ri_data - 1;
 	}
 
 	*rgcount = count1;
 	if (count1 != count2)
 		goto fail;
 
-	free(rgbh);
 	return 0;
 
  fail:
 	gfs2_rgrp_free(&sdp->rglist);
-	free(rgbh);
 	return -1;
 }
 
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 16bd1db..c158886 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -103,10 +103,11 @@ struct rgrp_list {
 	osi_list_t list;
 	uint64_t start;	   /* The offset of the beginning of this resource group */
 	uint64_t length;	/* The length of this resource group */
-	uint32_t rg_free;       /* Free blocks */
 
 	struct gfs2_rindex ri;
+	struct gfs2_rgrp rg;
 	struct gfs2_bitmap *bits;
+	struct gfs2_buffer_head **bh;
 };
 
 struct gfs2_buffer_head {
@@ -554,8 +555,7 @@ extern void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
 			   uint64_t *dblock, uint32_t *extlen, int prealloc);
 extern int gfs1_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
 		      unsigned int size);
-extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
-			    int *bitmap_blocks);
+extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1);
 extern int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet);
 extern struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp,
 					struct gfs2_buffer_head *bh);
@@ -680,11 +680,8 @@ int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head);
 /* rgrp.c */
 extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
 extern struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk);
-extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-			       struct gfs2_buffer_head **bh,
-			       struct gfs2_rgrp *rg);
-extern void gfs2_rgrp_relse(struct rgrp_list *rgd,
-			    struct gfs2_buffer_head **bh);
+extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
+extern void gfs2_rgrp_relse(struct rgrp_list *rgd);
 extern void gfs2_rgrp_free(osi_list_t *rglist);
 
 /* structures.c */
@@ -700,16 +697,15 @@ extern void build_root(struct gfs2_sbd *sdp);
 extern void do_init_inum(struct gfs2_sbd *sdp);
 extern void do_init_statfs(struct gfs2_sbd *sdp);
 extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type);
-extern int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-			     uint64_t *block, int first);
+extern int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
+			     int first);
 extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
 				 uint64_t *block, uint32_t type, int first);
 /* super.c */
 extern int check_sb(struct gfs2_sb *sb);
 extern int read_sb(struct gfs2_sbd *sdp);
 extern int ji_update(struct gfs2_sbd *sdp);
-extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1,
-		       int *bitmap_blocks);
+extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1);
 extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount);
 extern int write_sb(struct gfs2_sbd *sdp);
 
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index f4da1a0..c0f9e10 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -85,6 +85,14 @@ int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
 	    rgd->bits[length - 1].bi_len) * GFS2_NBBY != rgd->ri.ri_data)
 		return -1;
 
+	if (rgd->bh)      /* If we already have a bh allocated */
+		return 0; /* don't want to allocate another */
+	if(!(rgd->bh = (struct gfs2_buffer_head **)
+		 malloc(length * sizeof(struct gfs2_buffer_head *))))
+		return -1;
+	if(!memset(rgd->bh, 0, length * sizeof(struct gfs2_buffer_head *)))
+		return -1;
+
 	return 0;
 }
 
@@ -99,56 +107,63 @@ int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
 struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
 {
 	osi_list_t *tmp;
-	struct rgrp_list *rgd = NULL;
+	struct rgrp_list *rgd;
+	static struct rgrp_list *prev_rgd = NULL;
 	struct gfs2_rindex *ri;
 
-	for(tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
+	if (prev_rgd) {
+		ri = &prev_rgd->ri;
+		if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data)
+			return prev_rgd;
+	}
+
+	for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
 		ri = &rgd->ri;
 
-		if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data){
-			break;
-		} else
-			rgd = NULL;
+		if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data) {
+			prev_rgd = rgd;
+			return rgd;
+		}
 	}
-	return rgd;
+	return NULL;
 }
 
 /**
- * fs_rgrp_read - read in the resource group information from disk.
+ * gfs2_rgrp_read - read in the resource group information from disk.
  * @rgd - resource group structure
  * returns: 0 if no error, otherwise the block number that failed
  */
-uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-			struct gfs2_buffer_head **bh, struct gfs2_rgrp *rg)
+uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
 {
 	int x, length = rgd->ri.ri_length;
 
 	for (x = 0; x < length; x++){
-		bh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x);
-		if(gfs2_check_meta(bh[x],
+		rgd->bh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x);
+		if(gfs2_check_meta(rgd->bh[x],
 				   (x) ? GFS2_METATYPE_RB : GFS2_METATYPE_RG))
 		{
 			uint64_t error;
 
 			error = rgd->ri.ri_addr + x;
 			for (; x >= 0; x--)
-				brelse(bh[x]);
+				brelse(rgd->bh[x]);
 			return error;
 		}
 	}
 
-	gfs2_rgrp_in(rg, bh[0]->b_data);
-	rgd->rg_free = rg->rg_free;
+	gfs2_rgrp_in(&rgd->rg, rgd->bh[0]->b_data);
 	return 0;
 }
 
-void gfs2_rgrp_relse(struct rgrp_list *rgd, struct gfs2_buffer_head **bh)
+void gfs2_rgrp_relse(struct rgrp_list *rgd)
 {
 	int x, length = rgd->ri.ri_length;
 
-	for (x = 0; x < length; x++)
-		brelse(bh[x]);
+	for (x = 0; x < length; x++) {
+		brelse(rgd->bh[x]);
+		rgd->bh[x] = NULL;
+	}
 }
 
 void gfs2_rgrp_free(osi_list_t *rglist)
@@ -157,8 +172,14 @@ void gfs2_rgrp_free(osi_list_t *rglist)
 
 	while(!osi_list_empty(rglist->next)){
 		rgd = osi_list_entry(rglist->next, struct rgrp_list, list);
+		if (rgd->bh && rgd->bh[0]) /* if a buffer exists        */
+			gfs2_rgrp_relse(rgd); /* free them all. */
 		if(rgd->bits)
 			free(rgd->bits);
+		if(rgd->bh) {
+			free(rgd->bh);
+			rgd->bh = NULL;
+		}
 		osi_list_del(&rgd->list);
 		free(rgd);
 	}
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index b3e884d..89d0e12 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -488,14 +488,12 @@ int gfs2_set_meta(struct gfs2_buffer_head *bh, int type, int format)
  *
  * Returns: 0 on success, -1 when finished
  */
-int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-		      uint64_t *block, int first)
+int gfs2_next_rg_meta(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;
-	struct gfs2_buffer_head *bh;
 
 	if(!first && (*block < rgd->ri.ri_data0)) {
 		log_err("next_rg_meta:  Start block is outside rgrp bounds.\n");
@@ -509,17 +507,14 @@ int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
 	}
 	for(; i < length; i++){
 		bits = &rgd->bits[i];
-		bh = bread(&sdp->buf_list, rgd->ri.ri_addr + i);
-		blk = gfs2_bitfit((unsigned char *)bh->b_data +
+		blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data +
 				  bits->bi_offset, bits->bi_len, blk,
 				  GFS2_BLKST_DINODE);
 		if(blk != BFITNOENT){
 			*block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
-			brelse(bh);
 			break;
 		}
 		blk=0;
-		brelse(bh);
 	}
 	if(i == length)
 		return -1;
@@ -536,14 +531,14 @@ int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
  * Returns: 0 on success, -1 on error or finished
  */
 int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
-						  uint64_t *block, uint32_t type, int first)
+			  uint64_t *block, uint32_t type, int first)
 {
 	struct gfs2_buffer_head *bh = NULL;
 
 	do{
 		if (bh)
 			brelse(bh);
-		if (gfs2_next_rg_meta(sdp, rgd, block, first))
+		if (gfs2_next_rg_meta(rgd, block, first))
 			return -1;
 		bh = bread(&sdp->buf_list, *block);
 		first = 0;
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index 32407bc..debe0f6 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -175,7 +175,7 @@ int ji_update(struct gfs2_sbd *sdp)
  *
  * Returns: 0 on success, -1 on failure
  */
-int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *bitmap_blocks)
+int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
 {
 	unsigned int rg;
 	int error;
@@ -185,7 +185,6 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *bitmap_blocks)
 
 	*count1 = 0;
 	prev_rgd = NULL;
-	*bitmap_blocks = 0;
 	for (rg = 0; ; rg++) {
 		if (fd > 0)
 			error = read(fd, &buf, sizeof(struct gfs2_rindex));
@@ -208,8 +207,6 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *bitmap_blocks)
 
 		gfs2_rindex_in(&rgd->ri, (char *)&buf);
 
-		if (rgd->ri.ri_length > *bitmap_blocks)
-			*bitmap_blocks = rgd->ri.ri_length;
 		rgd->start = rgd->ri.ri_addr;
 		if (prev_rgd) {
 			prev_length = rgd->start - prev_rgd->start;
@@ -241,33 +238,19 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *bitmap_blocks)
 int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount)
 {
 	struct rgrp_list *rgd;
+	struct gfs2_rindex *ri;
 	osi_list_t *tmp;
 	int count1 = 0, count2 = 0;
 	uint64_t errblock = 0;
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head **rgbh = NULL;
-	int bitmap_blocks;
 
-	if (rindex_read(sdp, fd, &count1, &bitmap_blocks))
+	if (rindex_read(sdp, fd, &count1))
 	    goto fail;
-
-	if(!(rgbh = (struct gfs2_buffer_head **)
-	     malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *))))
-		return -1;
-	if(!memset(rgbh, 0, bitmap_blocks *
-		   sizeof(struct gfs2_buffer_head *))) {
-		free(rgbh);
-		return -1;
-	}
-
 	for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
 		rgd = osi_list_entry(tmp, struct rgrp_list, list);
-		errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rg);
-		if (errblock) {
-			free(rgbh);
+		errblock = gfs2_rgrp_read(sdp, rgd);
+		if (errblock)
 			return errblock;
-		} else
-			gfs2_rgrp_relse(rgd, rgbh);
+		ri = &rgd->ri;
 		count2++;
 	}
 
@@ -275,12 +258,10 @@ int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount)
 	if (count1 != count2)
 		goto fail;
 
-	free(rgbh);
 	return 0;
 
  fail:
 	gfs2_rgrp_free(&sdp->rglist);
-	free(rgbh);
 	return -1;
 }