cluster: RHEL6 - GFS2: mkfs.gfs2 segfaults with 18.55TB and -b512

Bob Peterson rpeterso at fedoraproject.org
Wed Jan 19 18:56:23 UTC 2011


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=d3af317da0bccfe12814c06c0723c0dd1657df17
Commit:        d3af317da0bccfe12814c06c0723c0dd1657df17
Parent:        1e9748b8e97b65454f4adbefbd684a44a2a13a6f
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Wed Jan 19 12:45:20 2011 -0600
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Wed Jan 19 12:57:06 2011 -0600

GFS2: mkfs.gfs2 segfaults with 18.55TB and -b512

The problem was that mkfs.gfs2 attempted to keep the number of resource
groups as low as possible, but in so doing, it chose a rgrp size that
required an enormous number of bitmap blocks per rgrp.  In fact, it
tried to use more than it could possibly address, given the small
block size.  Therefore, an error was flagged and mkfs.gfs2 aborted.
This patch ensures that mkfs.gfs2 chooses a rgrp size that takes into
account the maximum number of bitmap blocks.  If it hits the max
number of bitmap blocks, it backs off on its rgrp size and uses a
smaller size.  The smaller size rgrp ensures that a valid number of
bitmap blocks will be needed to represent all the blocks in each rgrp.

rhbz#624535
---
 gfs2/libgfs2/fs_geometry.c |   39 ++++++++++++++++++++++++++++++++-------
 1 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c
index a06e8a2..a15c31f 100644
--- a/gfs2/libgfs2/fs_geometry.c
+++ b/gfs2/libgfs2/fs_geometry.c
@@ -25,21 +25,42 @@
 static uint64_t how_many_rgrps(struct gfs2_sbd *sdp, struct device *dev, int rgsize_specified)
 {
 	uint64_t nrgrp;
+	uint32_t rgblocks1, rgblocksn, bitblocks1, bitblocksn;
+	int bitmap_overflow = 0;
 
 	while (TRUE) {
 		nrgrp = DIV_RU(dev->length, (sdp->rgsize << 20) / sdp->bsize);
 
-		if (rgsize_specified || /* If user specified an rg size or */
-			nrgrp <= GFS2_EXCESSIVE_RGS || /* not an excessive # of rgs or  */
-			sdp->rgsize >= 2048)     /* we've reached the max rg size */
+		/* check to see if the rg length overflows max # bitblks */
+		rgblocksn = dev->length / nrgrp;
+		rgblocks2bitblocks(sdp->bsize, &rgblocksn, &bitblocksn);
+		/* calculate size of the first rgrp */
+		rgblocks1 = dev->length - (nrgrp - 1) * (dev->length / nrgrp);
+		rgblocks2bitblocks(sdp->bsize, &rgblocks1, &bitblocks1);
+		if (bitblocks1 > 2149 || bitblocksn > 2149) {
+			bitmap_overflow = 1;
+			if (sdp->rgsize <= GFS2_DEFAULT_RGSIZE) {
+				fprintf(stderr, "error: It is not possible "
+					"to use the entire device with "
+					"block size %u bytes.\n",
+					sdp->bsize);
+				exit(-1);
+			}
+			sdp->rgsize -= GFS2_DEFAULT_RGSIZE; /* smaller rgs */
+			continue;
+		}
+		if (bitmap_overflow ||
+		    rgsize_specified || /* If user specified an rg size or */
+		    nrgrp <= GFS2_EXCESSIVE_RGS || /* not an excessive # or  */
+		    sdp->rgsize >= 2048)   /* we reached the max rg size */
 			break;
 
-		sdp->rgsize += GFS2_DEFAULT_RGSIZE; /* Try again w/bigger rgs */
+		sdp->rgsize += GFS2_DEFAULT_RGSIZE; /* bigger rgs */
 	}
 
 	if (sdp->debug)
-		printf("  rg sz = %"PRIu32"\n  nrgrp = %"PRIu64"\n", sdp->rgsize,
-			   nrgrp);
+		printf("  rg sz = %"PRIu32"\n  nrgrp = %"PRIu64"\n",
+		       sdp->rgsize, nrgrp);
 
 	return nrgrp;
 }
@@ -210,7 +231,11 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write)
 		rl->rg.rg_header.mh_format = GFS2_FORMAT_RG;
 		rl->rg.rg_free = rgblocks;
 
-		gfs2_compute_bitstructs(sdp, rl);
+		if (gfs2_compute_bitstructs(sdp, rl)) {
+			fprintf(stderr, "%s: Unable to build resource groups "
+				"with these characteristics.\n", __FUNCTION__);
+			exit(-1);
+		}
 
 		if (do_write) {
 			for (x = 0; x < bitblocks; x++) {


More information about the cluster-commits mailing list