gfs2_grow fails to grow a filesystem with less than 3 rgrps
A message that is not in the archive (sent off-list or not yet received): fc86251b-fb83-43f5-a81f-ca53c9000fcf@zmail06.collab.prod.int.phx2.redhat.com
PATCH 1/1 gfs2_grow fails to grow a filesystem with less than 3 rgrps
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(-)
gfs2/edit/savemeta.c +2 -4
@@ -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",
gfs2/libgfs2/fs_geometry.c +3 -3
@@ -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;
gfs2/libgfs2/libgfs2.h +5 -0
@@ -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);
gfs2/libgfs2/super.c +2 -2
@@ -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 ; }
gfs2/mkfs/main_grow.c +9 -18
@@ -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);
PATCH 1/1 gfs2_grow fails to grow a filesystem with less than 3 rgrps
Hi,
Looks good to me,
Steve.
Quoted 183 lines · Bob Peterson
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 successfullygfs2_growa file system that is so small that it has only one resource group. Also, "gfs2_editsavemeta" can't save it.This patch is designed to remedy the problem by
creating a genericrgrp_sizefunction in libgfs2
that calculates the size rather than judging its
distance from the previous rgrp.Testing results (today's
gfs2_growversus 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(-)gfs2/edit/savemeta.c +2
-4@@ -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",gfs2/libgfs2/fs_geometry.c +3
-3@@ -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;gfs2/libgfs2/libgfs2.h +5
-0@@ -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);gfs2/libgfs2/super.c +2
-2@@ -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 ; }gfs2/mkfs/main_grow.c +9
-18@@ -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);