[Cluster-devel] [PATCH] gfs2_edit savemeta: Don't read rgrps twice

Andrew Price anprice at redhat.com
Thu Feb 26 13:55:38 UTC 2015


By the time savemeta() is called the rindex has already been read into
memory, and before savemeta() processes each resource group it calls
gfs2_rgrp_read() to read in the rgrp header. It frees the rgrp once it's
done with it.

Strangely, before processing the resource groups, savemeta() reads the
superblock a second time and calls ri_update() which reads the rindex
again, as well as reading in every rgrp header to be kept in memory for
the duration. This caused high memory usage and a noticeable performance
reduction when saving metadata of large file systems.

To solve these problems, this patch removes the code which re-reads the
superblock, rindex and the rgrps. The code which reads the rindex has
been reorganised for clarity and the sbd.fssize field is now set
properly at that point.

With this patch, using a large fs, I'm seeing improvements similar to:

Before: 43:36.12elapsed 10822268maxresident k
After:  28:44.67elapsed   226980maxresident k

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/edit/hexedit.c  | 15 ++++++++++++--
 gfs2/edit/savemeta.c | 58 +++++++---------------------------------------------
 tests/edit.at        |  4 ++--
 3 files changed, 22 insertions(+), 55 deletions(-)

diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index dd4b625..4df1b9f 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -966,8 +966,6 @@ static int block_has_extended_info(void)
 /* ------------------------------------------------------------------------ */
 static void read_superblock(int fd)
 {
-	int count, sane;
-
 	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
 	memset(&sbd, 0, sizeof(struct gfs2_sbd));
@@ -1033,9 +1031,20 @@ static void read_superblock(int fd)
 			gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode);
 		}
 	}
+}
+
+static int read_rindex(void)
+{
+	struct gfs2_rindex *ri;
+	int count, sane;
+
 	sbd.fssize = sbd.device.length;
 	if (sbd.md.riinode) /* If we found the rindex */
 		rindex_read(&sbd, 0, &count, &sane);
+
+	ri = &((struct rgrp_tree *)osi_last(&sbd.rgtree))->ri;
+	sbd.fssize = ri->ri_data0 + ri->ri_data;
+	return 0;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -2539,6 +2548,8 @@ int main(int argc, char *argv[])
 	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
 
 	read_superblock(fd);
+	if (read_rindex())
+		exit(-1);
 	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
 	if (sbd.gfs1)
 		edit_row[GFS2_MODE]++;
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 5d30d28..b68b0ff 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -721,75 +721,32 @@ static int check_header(struct savemeta_header *smh)
 
 void savemeta(char *out_fn, int saveoption, int gziplevel)
 {
-	int rgcount;
 	uint64_t jindex_block;
 	struct gfs2_buffer_head *lbh;
 	struct metafd mfd;
-	int sane;
-	struct osi_node *n, *next = NULL;
+	struct osi_node *n;
 	int err = 0;
 
 	sbd.md.journals = 1;
 
 	mfd = savemetaopen(out_fn, gziplevel);
 
-	lseek(sbd.device_fd, 0, SEEK_SET);
 	blks_saved = 0;
-	if (!sbd.gfs1)
-		sbd.bsize = GFS2_DEFAULT_BSIZE;
-	if (lgfs2_get_dev_info(sbd.device_fd, &sbd.dinfo)) {
-		perror(device);
-		exit(-1);
-	}
-	fix_device_geometry(&sbd);
-	sbd.rgtree.osi_node = NULL;
-	if (!sbd.gfs1)
-		sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
-	if (compute_constants(&sbd)) {
-		fprintf(stderr, "Bad constants (1)\n");
-		exit(-1);
-	}
-	if (read_sb(&sbd) < 0) {
-		fprintf(stderr, "Unable to read superblock.\n");
-		exit(-1);
-	}
 	if (sbd.gfs1)
 		sbd.bsize = sbd.sd_sb.sb_bsize;
-	printf("There are %llu blocks of %u bytes in the destination "
-	       "device.\n", (unsigned long long)sbd.fssize, sbd.bsize);
-	if (sbd.gfs1) {
-		sbd.md.riinode = lgfs2_inode_read(&sbd, sbd1->sb_rindex_di.no_addr);
-		if (sbd.md.riinode == NULL) {
-			fprintf(stderr, "Unable to read rindex: %s.\n", strerror(errno));
-			exit(-1);
-		}
+	printf("There are %llu blocks of %u bytes in the filesystem.\n",
+	                     (unsigned long long)sbd.fssize, sbd.bsize);
+	if (sbd.gfs1)
 		jindex_block = sbd1->sb_jindex_di.no_addr;
-	} else {
-		sbd.master_dir = lgfs2_inode_read(&sbd,
-					    sbd.sd_sb.sb_master_dir.no_addr);
-		if (sbd.master_dir == NULL) {
-			fprintf(stderr, "Unable to read master: %s.\n", strerror(errno));
-			exit(-1);
-		}
-
-		gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode);
+	else
 		jindex_block = masterblock("jindex");
-	}
 	lbh = bread(&sbd, jindex_block);
 	gfs2_dinode_in(&di, lbh);
 	if (!sbd.gfs1)
 		do_dinode_extended(&di, lbh);
 	brelse(lbh);
 
-	printf("Reading resource groups...");
-	fflush(stdout);
-	if (sbd.gfs1)
-		gfs1_ri_update(&sbd, 0, &rgcount, 0);
-	else
-		ri_update(&sbd, 0, &rgcount, &sane);
-	printf("Done. File system size: %s\n\n", anthropomorphize(sbd.fssize * sbd.bsize));
-	fflush(stdout);
-
+	printf("Filesystem size: %s\n", anthropomorphize(sbd.fssize * sbd.bsize));
 	get_journal_inode_blocks();
 
 	/* Write the savemeta file header */
@@ -818,10 +775,9 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
 		}
 	}
 	/* Walk through the resource groups saving everything within */
-	for (n = osi_first(&sbd.rgtree); n; n = next) {
+	for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
 		struct rgrp_tree *rgd;
 
-		next = osi_next(n);
 		rgd = (struct rgrp_tree *)n;
 		if (gfs2_rgrp_read(&sbd, rgd))
 			continue;
diff --git a/tests/edit.at b/tests/edit.at
index e3f02e6..3bd4163 100644
--- a/tests/edit.at
+++ b/tests/edit.at
@@ -6,8 +6,8 @@ AT_KEYWORDS(gfs2_edit edit)
 GFS_TGT_REGEN
 AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT $(($(gfs_max_blocks 4096)/2))], 0, [ignore], [ignore])
 AT_CHECK([gfs2_edit savemeta $GFS_TGT test.meta > savemeta.log], 0, [ignore], [ignore])
-AT_CHECK([head -2 savemeta.log], 0, [There are 2621440 blocks of 4096 bytes in the destination device.
-Reading resource groups...Done. File system size: 4.1023GB
+AT_CHECK([head -2 savemeta.log], 0, [There are 1310718 blocks of 4096 bytes in the filesystem.
+Filesystem size: 4.1023GB
 ], [ignore])
 GFS_TGT_REGEN
 AT_CHECK([gfs2_edit restoremeta test.meta $GFS_TGT], 0, [ignore], [ignore])
-- 
1.9.3




More information about the Cluster-devel mailing list