Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=11068c6d...
Commit: 11068c6d81af4e3698ccebf54245b4891dbf53a8
Parent: 529ac229d44cfac4046e4b45ebd8b3f801252fd6
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Thu Apr 3 07:09:21 2014 -0500
Committer: Andrew Price <anprice(a)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(a)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);
}