[Cluster-devel] [gfs2-utils patch] gfs2_grow fails to grow a filesystem with less than 3 rgrps

Steven Whitehouse swhiteho at redhat.com
Fri Sep 30 15:25:23 UTC 2011


Hi,

Looks good to me,

Steve.

On Fri, 2011-09-30 at 11:13 -0400, Bob Peterson wrote:
> Hi,
> 
> There's a problem with gfs2-utils whereby some of the utils
> can't handle a small file system with one or two rgrps.
> The biggest offender is gfs2_grow: you can't successfully
> gfs2_grow a file system that is so small that it has only one
> resource group.  Also, "gfs2_edit savemeta" can't save it.
> 
> This patch is designed to remedy the problem by
> creating a generic rgrp_size function in libgfs2
> that calculates the size rather than judging its
> distance from the previous rgrp.
> 
> Testing results (today's gfs2_grow versus patched):
> # gfs2_grow /mnt/gfs2
> Segmentation fault (core dumped)
> # ./gfs2_grow /mnt/gfs2
> FS: Mount Point: /mnt/gfs2
> FS: Device:      /dev/mapper/vg_gfs2-lv_gfs2
> FS: Size:        127997 (0x1f3fd)
> FS: RG size:     127980 (0x1f3ec)
> DEV: Size:       256000 (0x3e800)
> The file system grew by 500MB.
> gfs2_grow complete.
> 
> Regards,
> 
> Bob Peterson
> Red Hat File Systems
> --
>  gfs2/edit/savemeta.c       |    6 ++----
>  gfs2/libgfs2/fs_geometry.c |    6 +++---
>  gfs2/libgfs2/libgfs2.h     |    5 +++++
>  gfs2/libgfs2/super.c       |    4 ++--
>  gfs2/mkfs/main_grow.c      |   27 +++++++++------------------
>  5 files changed, 21 insertions(+), 27 deletions(-)
> 
> diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
> index 9e5d111..31af23d 100644
> --- a/gfs2/edit/savemeta.c
> +++ b/gfs2/edit/savemeta.c
> @@ -637,7 +637,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
>  	int rgcount;
>  	uint64_t jindex_block;
>  	struct gfs2_buffer_head *lbh;
> -	struct rgrp_tree *last_rgd, *prev_rgd;
> +	struct rgrp_tree *last_rgd;
>  	struct metafd mfd;
>  
>  	slow = (saveoption == 1);
> @@ -715,9 +715,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
>  		n = osi_last(&sbd.rgtree);
>  		last_rgd = (struct rgrp_tree *)n;
>  		n = osi_prev(n);
> -		prev_rgd = (struct rgrp_tree *)n;
> -		fssize = last_rgd->ri.ri_addr +
> -			(last_rgd->ri.ri_addr - prev_rgd->ri.ri_addr);
> +		fssize = last_rgd->ri.ri_addr + rgrp_size(last_rgd);
>  		last_fs_block = fssize;
>  		fssize *= sbd.bsize;
>  		printf("Done. File system size: %s\n\n",
> diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c
> index 2b70f11..130331a 100644
> --- a/gfs2/libgfs2/fs_geometry.c
> +++ b/gfs2/libgfs2/fs_geometry.c
> @@ -80,8 +80,8 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, struct osi_root *rgtree,
>  	struct device *dev;
>  	struct rgrp_tree *rl, *rlast = NULL, *rlast2 = NULL;
>  	struct osi_node *n, *next = NULL;
> -	unsigned int rgrp = 0, nrgrp;
> -	uint64_t rglength, rgaddr;
> +	unsigned int rgrp = 0, nrgrp, rglength;
> +	uint64_t rgaddr;
>  
>  	sdp->new_rgrps = 0;
>  	dev = &sdp->device;
> @@ -113,7 +113,7 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, struct osi_root *rgtree,
>  			rlast = rl;
>  		}
>  		rlast->start = rlast->ri.ri_addr;
> -		rglength = rlast->ri.ri_addr - rlast2->ri.ri_addr;
> +		rglength = rgrp_size(rlast);
>  		rlast->length = rglength;
>  		old_length = rlast->ri.ri_addr + rglength;
>  		new_chunk = dev->length - old_length;
> diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
> index 53df6cd..77dfc29 100644
> --- a/gfs2/libgfs2/libgfs2.h
> +++ b/gfs2/libgfs2/libgfs2.h
> @@ -708,6 +708,11 @@ extern void gfs2_rgrp_relse(struct rgrp_tree *rgd);
>  extern struct rgrp_tree *rgrp_insert(struct osi_root *rgtree,
>  				     uint64_t rgblock);
>  extern void gfs2_rgrp_free(struct osi_root *rgrp_tree);
> +/* figure out the size of the given resource group, in blocks */
> +static inline unsigned int rgrp_size(struct rgrp_tree *rgrp)
> +{
> +	return rgrp->ri.ri_data + rgrp->ri.ri_length;
> +}
>  
>  /* structures.c */
>  extern int build_master(struct gfs2_sbd *sdp);
> diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
> index c354b07..c844287 100644
> --- a/gfs2/libgfs2/super.c
> +++ b/gfs2/libgfs2/super.c
> @@ -194,7 +194,7 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
>  					*sane = 0;
>  			}
>  			prev_length = rgd->start - prev_rgd->start;
> -			prev_rgd->length = prev_length;
> +			prev_rgd->length = rgrp_size(prev_rgd);
>  		}
>  
>  		if(gfs2_compute_bitstructs(sdp, rgd))
> @@ -204,7 +204,7 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
>  		prev_rgd = rgd;
>  	}
>  	if (prev_rgd)
> -		prev_rgd->length = prev_length;
> +		prev_rgd->length = rgrp_size(prev_rgd);
>  	return 0;
>  }
>  
> diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
> index dc092ee..7a32d7e 100644
> --- a/gfs2/mkfs/main_grow.c
> +++ b/gfs2/mkfs/main_grow.c
> @@ -122,23 +122,6 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
>  }
>  
>  /**
> - * figure_out_rgsize
> - */
> -static void figure_out_rgsize(struct gfs2_sbd *sdp, unsigned int *orgsize)
> -{
> -	struct osi_node *n = osi_first(&sdp->rgtree), *next = NULL;
> -	struct rgrp_tree *r1, *r2;
> -
> -	sdp->rgsize = GFS2_DEFAULT_RGSIZE;
> -	next = osi_next(n);
> -	r1 = (struct rgrp_tree *)next;
> -	next = osi_next(next);
> -	r2 = (struct rgrp_tree *)next;
> -
> -	*orgsize = r2->ri.ri_addr - r1->ri.ri_addr;
> -}
> -
> -/**
>   * filesystem_size - Calculate the size of the filesystem
>   *
>   * Reads the lists of resource groups in order to
> @@ -324,6 +307,7 @@ main_grow(int argc, char *argv[])
>  	
>  	while ((argc - optind) > 0) {
>  		int sane;
> +		struct rgrp_tree *last_rgrp;
>  
>  		sdp->path_name = argv[optind++];
>  		sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
> @@ -391,7 +375,13 @@ main_grow(int argc, char *argv[])
>  		/* the existing RGs, and only write to the index at EOF.    */
>  		ri_update(sdp, rindex_fd, &rgcount, &sane);
>  		fssize = filesystem_size(sdp);
> -		figure_out_rgsize(sdp, &rgsize);
> +		if (!sdp->rgtree.osi_node) {
> +			log_err(_("Error: No resource groups found.\n"));
> +			goto out;
> +		}
> +		last_rgrp = (struct rgrp_tree *)osi_last(&sdp->rgtree);
> +		sdp->rgsize = GFS2_DEFAULT_RGSIZE;
> +		rgsize = rgrp_size(last_rgrp);
>  		fsgrowth = ((sdp->device.length - fssize) * sdp->bsize);
>  		if (fsgrowth < rgsize * sdp->bsize) {
>  			log_err( _("Error: The device has grown by less than "
> @@ -409,6 +399,7 @@ main_grow(int argc, char *argv[])
>  			initialize_new_portion(sdp, &old_rg_count);
>  			fix_rindex(sdp, rindex_fd, old_rg_count);
>  		}
> +	out:
>  		/* Delete the remaining RGs from the rglist */
>  		gfs2_rgrp_free(&sdp->rgtree);
>  		close(rindex_fd);
> 





More information about the Cluster-devel mailing list