Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=11068c6d81a... Commit: 11068c6d81af4e3698ccebf54245b4891dbf53a8 Parent: 529ac229d44cfac4046e4b45ebd8b3f801252fd6 Author: Andrew Price anprice@redhat.com AuthorDate: Thu Apr 3 07:09:21 2014 -0500 Committer: Andrew Price anprice@redhat.com CommitterDate: Thu Apr 3 07:09:21 2014 -0500
gfs2_grow: Migrate to the new resource group API
Now that the foundations are in place, migrate gfs2_grow to the new resource group API in libgfs2. This fixes the problem of gfs2_grow using the last existing resource group's size as the size for all of the new resource groups. It also allows us to remove more direct usage of osi_tree.h structures and reduce usage of sdp->rgtree and sdp->rgcalc, which should be removed from that structure at some point.
It should now be trivial to add RAID stripe alignment to gfs2_grow.
Signed-off-by: Andrew Price anprice@redhat.com --- gfs2/mkfs/gfs2_mkfs.h | 1 - gfs2/mkfs/main_grow.c | 304 +++++++++++++++++++++++-------------------------- 2 files changed, 140 insertions(+), 165 deletions(-)
diff --git a/gfs2/mkfs/gfs2_mkfs.h b/gfs2/mkfs/gfs2_mkfs.h index 231f370..3c63858 100644 --- a/gfs2/mkfs/gfs2_mkfs.h +++ b/gfs2/mkfs/gfs2_mkfs.h @@ -8,7 +8,6 @@
/* main_grow */ extern void main_grow(int argc, char *argv[]); -extern void debug_print_rgrps(struct gfs2_sbd *sdp, struct osi_root *rgtree);
/* main_jadd */ extern void main_jadd(int argc, char *argv[]); diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c index 718bb30..88a7f15 100644 --- a/gfs2/mkfs/main_grow.c +++ b/gfs2/mkfs/main_grow.c @@ -133,137 +133,116 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp) }
/** - * filesystem_size - Calculate the size of the filesystem - * - * Reads the lists of resource groups in order to - * work out where the last block of the filesystem is located. - * + * Calculate the size of the filesystem + * Reads the lists of resource groups in order to work out where the last block + * of the filesystem is located. * Returns: The calculated size */ - -static uint64_t filesystem_size(struct gfs2_sbd *sdp) +static uint64_t filesystem_size(lgfs2_rgrps_t rgs) { - struct osi_node *n, *next = NULL; - struct rgrp_tree *rgl; - uint64_t size = 0, extent; - - for (n = osi_first(&sdp->rgtree); n; n = next) { - next = osi_next(n); - rgl = (struct rgrp_tree *)n; - extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data; - if (extent > size) - size = extent; - } - return size; + lgfs2_rgrp_t rg = lgfs2_rgrp_last(rgs); + const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg); + return ri->ri_data0 + ri->ri_data; }
/** - * initialize_new_portion - Write the new rg information to disk buffers. + * Write the new rg information to disk. */ -static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count) +static unsigned initialize_new_portion(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs) { - struct osi_node *n, *next = NULL; - uint64_t rgrp = 0; - struct rgrp_tree *rl; - - *old_rg_count = 0; - /* Delete the old RGs from the rglist */ - for (rgrp = 0, n = osi_first(&sdp->rgtree); - n && rgrp < (sdp->rgrps - sdp->new_rgrps); n = next, rgrp++) { - next = osi_next(n); - (*old_rg_count)++; - rl = (struct rgrp_tree *)n; - osi_erase(&rl->node, &sdp->rgtree); - free(rl); - } - /* Issue a discard ioctl for the new portion */ - rl = (struct rgrp_tree *)n; - discard_blocks(sdp->device_fd, rl->start * sdp->bsize, - (sdp->device.length - rl->start) * sdp->bsize); + unsigned rgcount = 0; + uint64_t rgaddr = fssize; + + discard_blocks(sdp->device_fd, rgaddr * sdp->bsize, fsgrowth * sdp->bsize); /* Build the remaining resource groups */ - if (build_rgrps(sdp, !test)) { - fprintf(stderr, _("Failed to build resource groups\n")); - exit(-1); + while (1) { + int err = 0; + lgfs2_rgrp_t rg; + struct gfs2_rindex ri; + rgaddr = lgfs2_rindex_entry_new(rgs, &ri, rgaddr, 0); + if (rgaddr == 0) + break; + rg = lgfs2_rgrps_append(rgs, &ri); + if (rg == NULL) { + perror(_("Failed to create resource group")); + return 0; + } + if (metafs_interrupted) + return 0; + if (sdp->debug) + printf(_("Writing resource group at %llu with size %"PRIu32"\n"), + ri.ri_addr, ri.ri_length + ri.ri_data); + if (!test) + err = lgfs2_rgrp_write(rgs, sdp->device_fd, rg); + if (err != 0) { + perror(_("Failed to write resource group")); + return 0; + } + rgcount++; } - - inode_put(&sdp->md.riinode); - inode_put(&sdp->master_dir); - - /* We're done with the libgfs portion, so commit it to disk. */ fsync(sdp->device_fd); + return rgcount; }
-/** - * fix_rindex - Add the new entries to the end of the rindex file. - */ -static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count) +static char *rindex_buffer(lgfs2_rgrps_t rgs, unsigned count) { - struct osi_node *n, *next = NULL; - int count, rg; - struct rgrp_tree *rl; - char *buf, *bufptr; - ssize_t writelen; - struct stat statbuf; + lgfs2_rgrp_t rg; + unsigned i = 0; + char *buf;
- /* Count the number of new RGs. */ - rg = 0; - for (n = osi_first(&sdp->rgtree); n; n = next) { - next = osi_next(n); - rg++; - } - log_info( _("%d new rindex entries.\n"), rg); - writelen = rg * sizeof(struct gfs2_rindex); - buf = calloc(1, writelen); + buf = calloc(count, sizeof(struct gfs2_rindex)); if (buf == NULL) { perror(__FUNCTION__); exit(EXIT_FAILURE); } - /* Now add the new rg entries to the rg index. Here we */ - /* need to use the gfs2 kernel code rather than the libgfs2 */ - /* code so we have a live update while mounted. */ - bufptr = buf; - for (n = osi_first(&sdp->rgtree); n; n = next) { - next = osi_next(n); - rg++; - rl = (struct rgrp_tree *)n; - gfs2_rindex_out(&rl->ri, bufptr); - bufptr += sizeof(struct gfs2_rindex); + for (rg = lgfs2_rgrp_first(rgs); rg; rg = lgfs2_rgrp_next(rg)) { + const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg); + gfs2_rindex_out(ri, buf + (sizeof(*ri) * i)); + i++; } - gfs2_rgrp_free(&sdp->rgtree); - fsync(sdp->device_fd); + return buf; +} + +/** + * fix_rindex - Add the new entries to the end of the rindex file. + */ +static void fix_rindex(int rindex_fd, lgfs2_rgrps_t rgs, unsigned old_rg_count, unsigned rgcount) +{ + char *buf; + ssize_t count; + ssize_t writelen; + const size_t entrysize = sizeof(struct gfs2_rindex); + + log_info( _("%d new rindex entries.\n"), rgcount); + buf = rindex_buffer(rgs, rgcount); + writelen = rgcount * entrysize; + if (!test) { - if (fstat(rindex_fd, &statbuf) != 0) { - perror("rindex"); - goto out; - } - if (statbuf.st_size != - old_rg_count * sizeof(struct gfs2_rindex)) { - log_crit(_("Incorrect rindex size. want %ld(%d resource groups), " - "have %ld\n"), - old_rg_count * sizeof(struct gfs2_rindex), - old_rg_count, statbuf.st_size); + off_t rindex_size = lseek(rindex_fd, 0, SEEK_END); + if (rindex_size != old_rg_count * entrysize) { + log_crit(_("Incorrect rindex size. Want %ld (%d resource groups), have %ld\n"), + (old_rg_count * entrysize), old_rg_count, rindex_size); goto out; } - /* Now write the new RGs to the end of the rindex */ - lseek(rindex_fd, 0, SEEK_END); - count = write(rindex_fd, buf, sizeof(struct gfs2_rindex)); - if (count != sizeof(struct gfs2_rindex)) { + /* Write the first entry separately to ensure there's enough + space in the fs for the rest */ + count = write(rindex_fd, buf, entrysize); + if (count != entrysize) { log_crit(_("Error writing first new rindex entry; aborted.\n")); if (count > 0) goto trunc; else goto out; } - count = write(rindex_fd, buf + sizeof(struct gfs2_rindex), - writelen - sizeof(struct gfs2_rindex)); - if (count != writelen - sizeof(struct gfs2_rindex)) { + count = write(rindex_fd, (buf + entrysize), (writelen - entrysize)); + if (count != (writelen - entrysize)) { log_crit(_("Error writing new rindex entries; aborted.\n")); if (count > 0) goto trunc; else goto out; } - if (fallocate(rindex_fd, FALLOC_FL_KEEP_SIZE, statbuf.st_size + writelen, sizeof(struct gfs2_rindex)) != 0) + if (fallocate(rindex_fd, FALLOC_FL_KEEP_SIZE, (rindex_size + writelen), entrysize) != 0) perror("fallocate"); fsync(rindex_fd); } @@ -284,46 +263,38 @@ trunc: */ static void print_info(struct gfs2_sbd *sdp) { - log_notice("FS: %-22s%s\n", _("Mount point:"), sdp->path_name); - log_notice("FS: %-22s%s\n", _("Device:"), sdp->device_name); - log_notice("FS: %-22s%llu (0x%llx)\n", _("Size:"), + log_notice("FS: %-25s%s\n", _("Mount point:"), sdp->path_name); + log_notice("FS: %-25s%s\n", _("Device:"), sdp->device_name); + log_notice("FS: %-25s%llu (0x%llx)\n", _("Size:"), (unsigned long long)fssize, (unsigned long long)fssize); - log_notice("FS: %-22s%u (0x%x)\n", _("Resource group size:"), rgsize, rgsize); - log_notice("DEV: %-22s%llu (0x%llx)\n", _("Length:"), + log_notice("FS: %-25s%u (0x%x)\n", _("New resource group size:"), rgsize, rgsize); + log_notice("DEV: %-24s%llu (0x%llx)\n", _("Length:"), (unsigned long long)sdp->device.length, (unsigned long long)sdp->device.length); - log_notice(_("The file system grew by %lluMB.\n"), - (unsigned long long)fsgrowth / MB); + log_notice(_("The file system will grow by %lluMB.\n"), + (unsigned long long)(fsgrowth * sdp->bsize) / MB); }
-void debug_print_rgrps(struct gfs2_sbd *sdp, struct osi_root *rgtree) +static void debug_print_rgrps(const char *banner, struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs) { - struct osi_node *n, *next; - struct rgrp_tree *rl; + lgfs2_rgrp_t r;
if (sdp->debug) { - log_info("\n"); - - for (n = osi_first(rgtree); n; n = next) { - next = osi_next(n); - rl = (struct rgrp_tree *)n; - log_info("rg_o = %llu, rg_l = %llu\n", - (unsigned long long)rl->start, - (unsigned long long)rl->length); + log_info("%s\n", banner); + + for (r = lgfs2_rgrp_first(rgs); r; r = lgfs2_rgrp_next(r)) { + const struct gfs2_rindex *ri = lgfs2_rgrp_index(r); + log_info("ri_addr = %llu, size = %llu\n", + (unsigned long long)ri->ri_addr, + (unsigned long long)(ri->ri_data0 + ri->ri_data - ri->ri_addr)); } } }
-/** - * main_grow - do everything - * @argc: - * @argv: - */ -void -main_grow(int argc, char *argv[]) +void main_grow(int argc, char *argv[]) { struct gfs2_sbd sbd, *sdp = &sbd; - int rgcount, rindex_fd; + int rindex_fd; char rindex_name[PATH_MAX]; int error = EXIT_SUCCESS; int devflags = (test ? O_RDONLY : O_RDWR) | O_CLOEXEC; @@ -337,9 +308,10 @@ main_grow(int argc, char *argv[]) decode_arguments(argc, argv, sdp); for(; (argc - optind) > 0; optind++) { - int sane; struct mntent *mnt; - struct rgrp_tree *last_rgrp; + unsigned rgcount; + unsigned old_rg_count; + lgfs2_rgrps_t rgs;
error = lgfs2_open_mnt(argv[optind], O_RDONLY|O_CLOEXEC, &sdp->path_fd, devflags, &sdp->device_fd, &mnt); @@ -358,10 +330,6 @@ main_grow(int argc, char *argv[]) perror(sdp->device_name); exit(EXIT_FAILURE); } - log_info( _("Initializing lists...\n")); - sdp->rgtree.osi_node = NULL; - sdp->rgcalc.osi_node = NULL; - sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE; sdp->bsize = sdp->sd_sb.sb_bsize; if (compute_constants(sdp)) { @@ -395,59 +363,67 @@ main_grow(int argc, char *argv[]) perror(_("Could not read master directory")); exit(EXIT_FAILURE); } - gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode); + rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0); + if (rgs == NULL) { + perror(_("Could not initialise resource groups")); + error = -1; + goto out; + } /* Fetch the rindex from disk. We aren't using gfs2 here, */ /* which means that the bitmaps will most likely be cached */ /* and therefore out of date. It shouldn't matter because */ /* we're only going to write out new RG information after */ /* the existing RGs, and only write to the index at EOF. */ - ri_update(sdp, rindex_fd, &rgcount, &sane); + log_info(_("Gathering resource group information for %s\n"), argv[optind]); + old_rg_count = lgfs2_rindex_read_fd(rindex_fd, rgs); + if (old_rg_count == 0) { + perror(_("Failed to scan existing resource groups")); + error = -EXIT_FAILURE; + goto out; + } if (metafs_interrupted) goto out; - fssize = filesystem_size(sdp); - if (!sdp->rgtree.osi_node) { - log_err(_("Error: No resource groups found.\n")); - error = -EXIT_FAILURE; + fssize = lgfs2_rgrp_align_addr(rgs, filesystem_size(rgs) + 1); + debug_print_rgrps(_("Existing resource groups"), sdp, rgs); + /* We're done with the old rgs now that we have the fssize and rg count */ + lgfs2_rgrps_free(&rgs); + /* Now lets set up the new ones with alignment and all */ + rgs = lgfs2_rgrps_init(sdp->bsize, sdp->device.length, 0, 0); + if (rgs == NULL) { + perror(_("Could not initialise new resource groups")); + error = -1; 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 " - "one resource group.\n")); - log_err( _("The device grew by %lluMB. "), - (unsigned long long)fsgrowth / MB); - log_err( _("One resource group is %uMB for this file system.\n"), - (rgsize * sdp->bsize) / MB); - error = -EXIT_FAILURE; + fsgrowth = (sdp->device.length - fssize); + rgsize = lgfs2_rgrps_plan(rgs, fsgrowth, ((GFS2_MAX_RGSIZE << 20) / sdp->bsize)); + if (rgsize < ((GFS2_MIN_RGSIZE << 20) / sdp->bsize)) { + log_err( _("The calculated resource group size is too small.\n")); + log_err( _("%s has not grown.\n"), argv[optind]); + error = -1; goto out; - } else { - int old_rg_count; - - if (metafs_interrupted) - goto out; - compute_rgrp_layout(sdp, &sdp->rgtree, TRUE); - if (metafs_interrupted) - goto out; - debug_print_rgrps(sdp, &sdp->rgtree); - print_info(sdp); - initialize_new_portion(sdp, &old_rg_count); - if (metafs_interrupted) - goto out; - fix_rindex(sdp, rindex_fd, old_rg_count); } + print_info(sdp); + rgcount = initialize_new_portion(sdp, rgs); + if (rgcount == 0 || metafs_interrupted) + goto out; + debug_print_rgrps(_("New resource groups"), sdp, rgs); + fsync(sdp->device_fd); + fix_rindex(rindex_fd, rgs, old_rg_count, rgcount); out: - /* Delete the remaining RGs from the rglist */ - gfs2_rgrp_free(&sdp->rgtree); + lgfs2_rgrps_free(&rgs); close(rindex_fd); cleanup_metafs(sdp); close(sdp->device_fd); + + if (metafs_interrupted) + break; } close(sdp->path_fd); sync(); - if (!metafs_interrupted) - log_notice( _("gfs2_grow complete.\n")); + if (metafs_interrupted) { + log_notice( _("gfs2_grow interrupted.\n")); + exit(1); + } + log_notice( _("gfs2_grow complete.\n")); exit(error); }
cluster-commits@lists.fedorahosted.org