cluster: RHEL56 - gfs2_convert: gfs2_convert uses too much memory for jdata conversion

Abhijith Das adas at fedoraproject.org
Fri Apr 30 15:44:38 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=df2ed5c24c9780323e8412057747c4751ef66acb
Commit:        df2ed5c24c9780323e8412057747c4751ef66acb
Parent:        e16c5e55e999c8f928c398a7afc7f100063d0c7f
Author:        Abhijith Das <adas at redhat.com>
AuthorDate:    Fri Apr 30 10:42:03 2010 -0500
Committer:     Abhijith Das <adas at redhat.com>
CommitterDate: Fri Apr 30 10:42:03 2010 -0500

gfs2_convert: gfs2_convert uses too much memory for jdata conversion

Moved some code around so that the data blocks of the
jdata file are not mapped into buffers in advance.
Instead, only indirect blocks one level below are mapped.
The data blocks are then mapped one-by-one while they're
copied onto the new converted jdata file.

Resolves: rhbz#571876
Signed-off-by: Abhi Das <adas at redhat.com>
---
 gfs2/convert/gfs2_convert.c |  105 +++++++++++++++++++++++++++++-------------
 gfs2/libgfs2/fs_ops.c       |    1 +
 2 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 5a45c96..5f63bc4 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -322,8 +322,7 @@ static void fix_metatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
 		bh = ip->i_bh;
 		/* First, build up the metatree */
 		for (h = 0; h < blk->height; h++) {
-			lookup_block(ip, ip->i_bh, h, &blk->mp, 1, &new,
-				     &block);
+			lookup_block(ip, bh, h, &blk->mp, 1, &new, &block);
 			if (bh != ip->i_bh)
 				brelse(bh);
 			if (!block)
@@ -674,6 +673,7 @@ void fix_jdatatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
 		memcpy(bh->b_data + ptramt,
 		       (char *)srcptr, amount);
 		srcptr += amount;
+		bmodified(bh);
 		if (bh != ip->i_bh)
 			brelse(bh);
 
@@ -748,16 +748,14 @@ int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
 	       sbp->bsize - sizeof(struct gfs_dinode));
 	osi_list_add_prev(&blk->list, &blocks.list);
 
-	/* Now run the metadata chain and build lists of all data/metadata blocks */
+	/* Now run the metadata chain and build lists of all metadata blocks */
 	osi_list_foreach(tmp, &blocks.list) {
 		blk = osi_list_entry(tmp, struct blocklist, list);
 
-		if (blk->height >= ip->i_di.di_height)
+		if (blk->height >= ip->i_di.di_height - 1)
 			continue;
-
 		header_size = (blk->height > 0 ? sizeof(struct gfs_indirect) :
 			       sizeof(struct gfs_dinode));
-
 		for (ptr1 = (uint64_t *)blk->ptrbuf, ptrnum = 0;
 		     ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
 			if (!*ptr1)
@@ -790,23 +788,14 @@ int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
 			/* Queue it to be processed later on in the loop. */
 			osi_list_add_prev(&newblk->list, &blocks.list);
 
+			/* read the new metadata block's pointers */
 			bh = bread(sbp, block);
-			if (newblk->height == ip->i_di.di_height) {
-				/* read in the jdata block */
-				memcpy(newblk->ptrbuf, bh->b_data +
-				       sizeof(struct gfs2_meta_header), bufsize);
-				/* Zero the buffer so we can fill it in later */
-				memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
-				       bufsize);
-			} else {
-				/* read the new metadata block's pointers */
-				memcpy(newblk->ptrbuf, bh->b_data +
-				       sizeof(struct gfs_indirect),
-				       sbp->bsize - sizeof(struct gfs_indirect));
-				/* Zero the buffer so we can fill it in later */
-				memset(bh->b_data + sizeof(struct gfs_indirect), 0,
-				       sbp->bsize - sizeof(struct gfs_indirect));
-			}
+			memcpy(newblk->ptrbuf, bh->b_data + sizeof(struct gfs_indirect),
+				sbp->bsize - sizeof(struct gfs_indirect));
+			/* Zero the buffer so we can fill it in later */
+			memset(bh->b_data + sizeof(struct gfs_indirect), 0,
+				sbp->bsize - sizeof(struct gfs_indirect));
+			bmodified(bh);
 			brelse(bh);
 			/* Free the block so we can reuse it. This allows us to
 			   convert a "full" file system. */
@@ -831,18 +820,68 @@ int adjust_jdata_inode(struct gfs2_sbd *sbp, struct gfs2_inode *ip)
 
 		blk = osi_list_entry(tmp, struct blocklist, list);
 		/* If it's not a data block at the highest level */
-		if (blk->height != di_height) {
+		if (blk->height != di_height - 1) {
 			osi_list_del(tmp);
 			free(blk->ptrbuf);
 			free(blk);
 			continue;
 		}
-		len = bufsize;
-		jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &blk->mp, &gfs2mp, &len, dinode_size);
-		memcpy(&blk->mp, &gfs2mp, sizeof(struct metapath));
-		blk->height -= di_height - gfs2_hgt;
-		if (len)
-			fix_jdatatree(sbp, ip, blk, blk->ptrbuf, len);
+		/*
+		 * For each metadata block that holds jdata block pointers,
+		 * get the blk pointers and copy them block by block
+		 */
+		for (ptr1 = (uint64_t *) blk->ptrbuf, ptrnum = 0;
+		     ptrnum < sbp->sd_inptrs; ptr1++, ptrnum++) {
+			if (!*ptr1)
+				continue;
+			block = be64_to_cpu(*ptr1);
+
+			newblk = malloc(sizeof(struct blocklist));
+			if (!newblk) {
+				log_crit("Error: Can't allocate memory"
+					 " for indirect block fix.\n");
+				error = -1;
+				goto out;
+			}
+			memset(newblk, 0, sizeof(*newblk));
+			newblk->ptrbuf = malloc(bufsize); 
+			if (!newblk->ptrbuf) {
+				log_crit("Error: Can't allocate memory"
+					 " for file conversion.\n");
+				free(newblk);
+				goto out;
+			}
+			memset(newblk->ptrbuf, 0, bufsize);
+			newblk->block = block;
+			newblk->height = blk->height + 1;
+			/* Build the metapointer list from our predecessors */
+			for (h=0; h < blk->height; h++)
+				newblk->mp.mp_list[h] = blk->mp.mp_list[h];
+			newblk->mp.mp_list[h] = ptrnum;
+			bh = bread(sbp, block);
+			/* This is a data block. i.e newblk->height == ip->i_di.di_height */
+			/* read in the jdata block */
+			memcpy(newblk->ptrbuf, bh->b_data +
+			       sizeof(struct gfs2_meta_header), bufsize);
+			memset(bh->b_data + sizeof(struct gfs2_meta_header), 0,
+			       bufsize);
+			bmodified(bh);
+			brelse(bh);
+			/* Free the block so we can reuse it. This allows us to
+			   convert a "full" file system */
+			ip->i_di.di_blocks--;
+			gfs2_free_block(sbp, block);
+
+			len = bufsize;
+			jdata_mp_gfs1_to_gfs2(sbp, di_height, gfs2_hgt, &newblk->mp, &gfs2mp,
+					      &len, dinode_size);
+			memcpy(&newblk->mp, &gfs2mp, sizeof(struct metapath));
+			newblk->height -= di_height - gfs2_hgt;
+			if (len)
+				fix_jdatatree(sbp, ip, newblk, newblk->ptrbuf, len);
+			free(newblk->ptrbuf);
+			free(newblk);
+		}
 		osi_list_del(tmp);
 		free(blk->ptrbuf);
 		free(blk);
@@ -942,10 +981,10 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
 		inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
 		inode->i_di.di_goal_data = gfs1_dinode_struct->di_goal_dblk;
 		inode->i_di.di_generation = 0;
-		if (!(inode->i_di.di_mode & S_IFDIR) && 
+		if (!(inode->i_di.di_mode & S_IFDIR) &&
 		    inode->i_di.di_flags & GFS2_DIF_JDATA)
 			ret = adjust_jdata_inode(sbp, inode);
-		else 
+		else
 			ret = adjust_indirect_blocks(sbp, inode);
 		if (ret)
 			return -1;
@@ -1011,9 +1050,9 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr)
 				sbp->sd_sb.sb_root_dir.no_formal_ino = sbp->md.next_inum;
 			}
 			bh = bread(sbp, block);
-			if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) /* if it is an dinode */
+			if (!gfs2_check_meta(bh, GFS_METATYPE_DI)) {/* if it is an dinode */
 				error = adjust_inode(sbp, bh);
-			else { /* It's metadata, but not an inode, so fix the bitmap. */
+			} else { /* It's metadata, but not an inode, so fix the bitmap. */
 				int blk, buf_offset;
 				int bitmap_byte; /* byte within the bitmap to fix */
 				int byte_bit; /* bit within the byte */
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index aed34c6..9aeeb23 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -931,6 +931,7 @@ static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex,
 	dip->i_di.di_blocks++;
 	bmodified(dip->i_bh);
 
+	bmodified(obh); /* Need to do this in case nothing was moved */
 	brelse(obh);
 	bmodified(nbh);
 	brelse(nbh);


More information about the cluster-commits mailing list