Cluster Project branch, RHEL5, updated. cmirror_1_1_15-161-g5ff7b66

rpeterso@sourceware.org rpeterso@sourceware.org
Mon Jul 21 22:48:00 GMT 2008


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Cluster Project".

http://sources.redhat.com/git/gitweb.cgi?p=cluster.git;a=commitdiff;h=5ff7b6671b739796e5c3f4f2f8cc0005015936cc

The branch, RHEL5 has been updated
       via  5ff7b6671b739796e5c3f4f2f8cc0005015936cc (commit)
       via  e9edb213078c4d59a5f229a98cb157fcbe977df8 (commit)
       via  dee2b071cdace918515cddd1904df1d5d86c7dfc (commit)
       via  7492a086097d72db89d105f0f38004e7a106a1c4 (commit)
       via  28610e88b1706a296780193bbb7b6072bb972c24 (commit)
       via  8a4a16fd453c507b6d9aa492b5f0bbb687b40c64 (commit)
       via  4a138cb97b20c1abd2aa4c7740a27d80b3a060eb (commit)
       via  47f97db79bef3295e490c86bdefc37ba5c58e58e (commit)
       via  ddcf644dfa303fb2ca2363a6f34033438dd358c7 (commit)
       via  6d4364e8aaec211b27ce19ae2997351d7d179263 (commit)
       via  d4b869fcf12cdae55f9558d69dc254aa675b09e8 (commit)
      from  b2916471b1b7c79dba7f9624a1a148240375891f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5ff7b6671b739796e5c3f4f2f8cc0005015936cc
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Wed Jul 16 19:02:56 2008 -0500

    Print log header flags for gfs journals.

commit e9edb213078c4d59a5f229a98cb157fcbe977df8
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Jul 10 16:12:53 2008 -0500

    Fix some minor white space issues.

commit dee2b071cdace918515cddd1904df1d5d86c7dfc
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Mon Jun 23 10:11:35 2008 -0500

    savemeta was not saving gfs1 journals properly.

commit 7492a086097d72db89d105f0f38004e7a106a1c4
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Jun 5 18:00:07 2008 -0500

    Ability to specify starting block or structure with -s

commit 28610e88b1706a296780193bbb7b6072bb972c24
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Jun 5 16:23:37 2008 -0500

    Allow keywords in block number input

commit 8a4a16fd453c507b6d9aa492b5f0bbb687b40c64
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Jun 5 13:47:16 2008 -0500

    Updates to gfs2_edit man page for new options.

commit 4a138cb97b20c1abd2aa4c7740a27d80b3a060eb
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Wed Jun 4 08:39:20 2008 -0500

    Fix gfs2_edit bugs with non-4K block sizes

commit 47f97db79bef3295e490c86bdefc37ba5c58e58e
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Apr 10 10:45:47 2008 -0500

    Fix some compiler warnings in gfs2_edit

commit ddcf644dfa303fb2ca2363a6f34033438dd358c7
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Apr 10 10:45:47 2008 -0500

    gfs2_edit was not recalculating the max block size after it figured
    that out.

commit 6d4364e8aaec211b27ce19ae2997351d7d179263
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Tue Mar 18 15:44:24 2008 -0500

    Fix gfs2_edit print options (-p) to work properly for gfs-1
    rgs and rindex.  Also fixed rgflags option for gfs1.

commit d4b869fcf12cdae55f9558d69dc254aa675b09e8
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Tue Mar 11 18:18:43 2008 -0500

    Fix savemeta so it saves gfs-1 rg information properly
    Also add savergs option to facilitate rg-only repairs.

-----------------------------------------------------------------------

Summary of changes:
 gfs2/edit/gfs2hex.c  |   28 ++--
 gfs2/edit/hexedit.c  |  461 ++++++++++++++++++++++++++++++++------------------
 gfs2/edit/hexedit.h  |   34 ++++-
 gfs2/edit/savemeta.c |  109 ++++++++-----
 gfs2/man/gfs2_edit.8 |   51 ++++++-
 5 files changed, 459 insertions(+), 224 deletions(-)

diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index a56b4ee..082f5b6 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -38,7 +38,6 @@
 extern struct gfs2_sb sb;
 extern char *buf;
 extern struct gfs2_dinode di;
-extern uint64_t bufsize;
 extern int line, termlines;
 extern char edit_fmt[80];
 extern char estring[1024];
@@ -70,9 +69,9 @@ void print_gfs2(const char *fmt, ...)
 	va_start(args, fmt);
 	vsprintf(string, fmt, args);
 	if (termlines)
-		printw(string);
+		printw("%s", string);
 	else
-		printf(string);
+		printf("%s", string);
 	va_end(args);
 }
 
@@ -127,9 +126,9 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 		vsprintf(tmp_string, fmt, args);
 
 		if (termlines)
-			printw(tmp_string);
+			printw("%s", tmp_string);
 		else
-			printf(tmp_string);
+			printf("%s", tmp_string);
 		check_highlight(FALSE);
 
 		if (fmt2) {
@@ -159,10 +158,10 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 				fmtstring="(decimal)";
 			if (termlines) {
 				move(line, 50);
-				printw(fmtstring);
+				printw("%s", fmtstring);
 			}
 			else
-				printf(fmtstring);
+				printf("%s", fmtstring);
 		}
 		if (termlines) {
 			refresh();
@@ -226,9 +225,8 @@ void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 	memset(indirect, 0, sizeof(indirect));
 	if (di->di_height > 0) {
 		/* Indirect pointers */
-		for (x = sizeof(struct gfs2_dinode), y = 0;
-			 x < bufsize;
-			 x += sizeof(uint64_t), y++) {
+		for (x = sizeof(struct gfs2_dinode); x < sbd.bsize;
+			 x += sizeof(uint64_t)) {
 			p = be64_to_cpu(*(uint64_t *)(buf + x));
 			if (p) {
 				indirect->ii[indirect_blocks].block = p;
@@ -244,7 +242,7 @@ void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 		indirect->ii[0].dirents = 0;
 		indirect->ii[0].block = block;
 		indirect->ii[0].is_dir = TRUE;
-		for (x = sizeof(struct gfs2_dinode); x < bufsize; x += skip) {
+		for (x = sizeof(struct gfs2_dinode); x < sbd.bsize; x += skip) {
 			skip = indirect_dirent(indirect->ii,
 					       buf + x,
 					       indirect->ii[0].dirents);
@@ -276,7 +274,7 @@ void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 				gfs2_leaf_in(&leaf, tmp_bh->b_data);
 				indirect->ii[indirect_blocks].dirents = 0;
 				for (direntcount = 0, bufoffset = sizeof(struct gfs2_leaf);
-					 bufoffset < bufsize;
+					 bufoffset < sbd.bsize;
 					 direntcount++, bufoffset += skip) {
 					skip = indirect_dirent(&indirect->ii[indirect_blocks],
 										   tmp_bh->b_data + bufoffset,
@@ -318,7 +316,7 @@ int do_indirect_extended(char *buf, struct iinfo *iinf)
 	memset(iinf, 0, sizeof(struct iinfo));
 	for (x = (gfs1 ? sizeof(struct gfs_indirect):
 			  sizeof(struct gfs2_meta_header)), y = 0;
-		 x < bufsize;
+		 x < sbd.bsize;
 		 x += sizeof(uint64_t), y++) {
 		p = be64_to_cpu(*(uint64_t *)(buf + x));
 		if (p) {
@@ -353,7 +351,7 @@ void do_leaf_extended(char *buf, struct iinfo *indir)
 	x = 0;
 	memset(indir, 0, sizeof(indir));
 	/* Directory Entries: */
-	for (i = sizeof(struct gfs2_leaf); i < bufsize;
+	for (i = sizeof(struct gfs2_leaf); i < sbd.bsize;
 	     i += de.de_rec_len) {
 		gfs2_dirent_in(&de, buf + i);
 		if (de.de_inum.no_addr) {
@@ -400,7 +398,7 @@ void do_eattr_extended(char *buf)
 	print_gfs2("Eattr Entries:");
 	eol(0);
 
-	for (x = sizeof(struct gfs2_meta_header); x < bufsize; x += ea.ea_rec_len)
+	for (x = sizeof(struct gfs2_meta_header); x < sbd.bsize; x += ea.ea_rec_len)
 	{
 		eol(0);
 		gfs2_ea_header_in(&ea, buf + x);
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index df94600..b169135 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -387,7 +387,7 @@ int display_block_type(const char *lpBuffer, int from_restore)
 	}
 	if (block == RGLIST_DUMMY_BLOCK) {
 		ret_type = GFS2_METATYPE_RG;
-		struct_len = sizeof(struct gfs2_rgrp);
+		struct_len = gfs1 ? sizeof(struct gfs_rgrp) : sizeof(struct gfs2_rgrp);
 	}
 	else if ((ret_type = get_block_type(lpBuffer))) {
 		switch (*(lpBuffer+7)) {
@@ -469,8 +469,8 @@ int display_block_type(const char *lpBuffer, int from_restore)
 		if (!screen_chunk_size)
 			screen_chunk_size = 256;
 		print_gfs2("(p.%d of %d)", (offset / screen_chunk_size) + 1,
-				   (bufsize % screen_chunk_size) > 0 ? 
-				   bufsize / screen_chunk_size + 1 : bufsize / 
+				   (sbd.bsize % screen_chunk_size) > 0 ?
+				   sbd.bsize / screen_chunk_size + 1 : sbd.bsize /
 				   screen_chunk_size);
 		/*eol(9);*/
 	}
@@ -534,7 +534,7 @@ int hexdump(uint64_t startaddr, const char *lpBuffer, int len)
 			line < termlines &&
 			line <= ((screen_chunk_size / 16) + 2)) ||
 			(!termlines && l < len)) &&
-		   l < bufsize) {
+		   l < sbd.bsize) {
 		if (termlines) {
 			move(line, 0);
 			COLORS_OFFSETS; /* cyan for offsets */
@@ -618,6 +618,17 @@ uint64_t masterblock(const char *fn)
 }
 
 /* ------------------------------------------------------------------------ */
+/* risize - size of one rindex entry, whether gfs1 or gfs2                  */
+/* ------------------------------------------------------------------------ */
+static int risize(void)
+{
+	if (gfs1)
+		return sizeof(struct gfs_rindex);
+	else
+		return sizeof(struct gfs2_rindex);
+}
+
+/* ------------------------------------------------------------------------ */
 /* rgcount - return how many rgrps there are.                               */
 /* ------------------------------------------------------------------------ */
 void rgcount(void)
@@ -633,7 +644,7 @@ void rgcount(void)
 	ribh = bread(&sbd, block);
 	riinode = inode_get(&sbd, ribh);
 	printf("%lld RGs in this file system.\n",
-	       riinode->i_di.di_size / sizeof(struct gfs2_rindex));
+	       (unsigned long long)riinode->i_di.di_size / risize());
 	inode_put(riinode, not_updated);
 	exit(EXIT_SUCCESS);
 }
@@ -646,10 +657,18 @@ uint64_t find_rgrp_block(struct gfs2_inode *di, int rg)
 	char buf[sizeof(struct gfs2_rindex)];
 	int amt;
 	struct gfs2_rindex ri;
+	uint64_t offset, gfs1_adj = 0;
 
-	amt = gfs2_readi(di, (void *)&buf,
-			 rg * sizeof(struct gfs2_rindex),
-			 sizeof(struct gfs2_rindex));
+	offset = rg * risize();
+	if (gfs1) {
+		uint64_t sd_jbsize =
+			(sbd.bsize - sizeof(struct gfs2_meta_header));
+
+		gfs1_adj = (offset / sd_jbsize) *
+			sizeof(struct gfs2_meta_header);
+		gfs1_adj += sizeof(struct gfs2_meta_header);
+	}
+	amt = gfs2_readi(di, (void *)&buf, offset + gfs1_adj, risize());
 	if (!amt) /* end of file */
 		return 0;
 	gfs2_rindex_in(&ri, buf);
@@ -657,56 +676,126 @@ uint64_t find_rgrp_block(struct gfs2_inode *di, int rg)
 }
 
 /* ------------------------------------------------------------------------ */
-/* set_rgrp_flags - Set an rgrp's flags to a given value                    */
-/* rgnum: which rg to print or modify flags for (0 - X)                     */
-/* new_flags: value to set new rg_flags to (if modify == TRUE)              */
-/* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
-/* full: TRUE if the full RG should be printed.                             */
+/* gfs_rgrp_in - Read in a resource group header                            */
 /* ------------------------------------------------------------------------ */
-void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
+void gfs_rgrp_in(struct gfs_rgrp *rgrp, char *buf)
+{
+	struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
+
+	gfs2_meta_header_in(&rgrp->rg_header, buf);
+	rgrp->rg_flags = be32_to_cpu(str->rg_flags);
+	rgrp->rg_free = be32_to_cpu(str->rg_free);
+	rgrp->rg_useddi = be32_to_cpu(str->rg_useddi);
+	rgrp->rg_freedi = be32_to_cpu(str->rg_freedi);
+	gfs2_inum_in(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
+	rgrp->rg_usedmeta = be32_to_cpu(str->rg_usedmeta);
+	rgrp->rg_freemeta = be32_to_cpu(str->rg_freemeta);
+}
+
+/* ------------------------------------------------------------------------ */
+/* gfs_rgrp_out */
+/* ------------------------------------------------------------------------ */
+void gfs_rgrp_out(struct gfs_rgrp *rgrp, char *buf)
+{
+	struct gfs_rgrp *str = (struct gfs_rgrp *)buf;
+
+	gfs2_meta_header_out(&rgrp->rg_header, buf);
+	str->rg_flags = cpu_to_be32(rgrp->rg_flags);
+	str->rg_free = cpu_to_be32(rgrp->rg_free);
+	str->rg_useddi = cpu_to_be32(rgrp->rg_useddi);
+	str->rg_freedi = cpu_to_be32(rgrp->rg_freedi);
+	gfs2_inum_out(&rgrp->rg_freedi_list, (char *)&str->rg_freedi_list);
+	str->rg_usedmeta = cpu_to_be32(rgrp->rg_usedmeta);
+	str->rg_freemeta = cpu_to_be32(rgrp->rg_freemeta);
+}
+
+/* ------------------------------------------------------------------------ */
+/* gfs_rgrp_print - print a gfs1 resource group                             */
+/* ------------------------------------------------------------------------ */
+void gfs_rgrp_print(struct gfs_rgrp *rg)
 {
-	struct gfs2_rgrp rg;
-	struct gfs2_buffer_head *bh, *ribh;
-	uint64_t rgblk, block;
+	gfs2_meta_header_print(&rg->rg_header);
+	pv(rg, rg_flags, "%u", "0x%x");
+	pv(rg, rg_free, "%u", "0x%x");
+	pv(rg, rg_useddi, "%u", "0x%x");
+	pv(rg, rg_freedi, "%u", "0x%x");
+	gfs2_inum_print(&rg->rg_freedi_list);
+	pv(rg, rg_usedmeta, "%u", "0x%x");
+	pv(rg, rg_freemeta, "%u", "0x%x");
+}
+
+/* ------------------------------------------------------------------------ */
+/* get_rg_addr                                                              */
+/* ------------------------------------------------------------------------ */
+uint64_t get_rg_addr(int rgnum)
+{
+	struct gfs2_buffer_head *bh;
+	uint64_t rgblk = 0, block;
 	struct gfs2_inode *riinode;
 
 	if (gfs1)
 		block = sbd1->sb_rindex_di.no_addr;
 	else
 		block = masterblock("rindex");
-	ribh = bread(&sbd, block);
-	riinode = inode_get(&sbd, ribh);
-	if (rgnum >= riinode->i_di.di_size / sizeof(struct gfs2_rindex)) {
+	bh = bread(&sbd, block);
+	riinode = inode_get(&sbd, bh);
+	if (rgnum < riinode->i_di.di_size / risize())
+		rgblk = find_rgrp_block(riinode, rgnum);
+	else
 		fprintf(stderr, "Error: File system only has %lld RGs.\n",
-		       riinode->i_di.di_size / sizeof(struct gfs2_rindex));
-		inode_put(riinode, not_updated);
-		brelse(ribh, not_updated);
-		return;
-	}
-	rgblk = find_rgrp_block(riinode, rgnum);
+			(unsigned long long)riinode->i_di.di_size / risize());
+	inode_put(riinode, not_updated);
+	return rgblk;
+}
+
+/* ------------------------------------------------------------------------ */
+/* set_rgrp_flags - Set an rgrp's flags to a given value                    */
+/* rgnum: which rg to print or modify flags for (0 - X)                     */
+/* new_flags: value to set new rg_flags to (if modify == TRUE)              */
+/* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
+/* full: TRUE if the full RG should be printed.                             */
+/* ------------------------------------------------------------------------ */
+void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
+{
+	union {
+		struct gfs2_rgrp rg2;
+		struct gfs_rgrp rg1;
+	} rg;
+	struct gfs2_buffer_head *bh;
+	uint64_t rgblk;
+
+	rgblk = get_rg_addr(rgnum);
 	bh = bread(&sbd, rgblk);
-	gfs2_rgrp_in(&rg, bh->b_data);
+	if (gfs1)
+		gfs_rgrp_in(&rg.rg1, bh->b_data);
+	else
+		gfs2_rgrp_in(&rg.rg2, bh->b_data);
 	if (modify) {
 		printf("RG #%d (block %llu / 0x%llx) rg_flags changed from 0x%08x to 0x%08x\n",
 		       rgnum, (unsigned long long)rgblk,
-		       (unsigned long long)rgblk, rg.rg_flags, new_flags);
-		rg.rg_flags = new_flags;
-		gfs2_rgrp_out(&rg, bh->b_data);
+		       (unsigned long long)rgblk, rg.rg2.rg_flags, new_flags);
+		rg.rg2.rg_flags = new_flags;
+		if (gfs1)
+			gfs_rgrp_out(&rg.rg1, bh->b_data);
+		else
+			gfs2_rgrp_out(&rg.rg2, bh->b_data);
 		brelse(bh, updated);
 	} else {
 		if (full) {
 			print_gfs2("RG #%d", rgnum);
 			print_gfs2(" located at: %llu (0x%llx)", rgblk, rgblk);
                         eol(0);
-			gfs2_rgrp_print(&rg);
+			if (gfs1)
+				gfs_rgrp_print(&rg.rg1);
+			else
+				gfs2_rgrp_print(&rg.rg2);
 		}
 		else
 			printf("RG #%d (block %llu / 0x%llx) rg_flags = 0x%08x\n",
 			       rgnum, (unsigned long long)rgblk,
-			       (unsigned long long)rgblk, rg.rg_flags);
+			       (unsigned long long)rgblk, rg.rg2.rg_flags);
 		brelse(bh, not_updated);
 	}
-	inode_put(riinode, not_updated);
 	if (modify)
 		bsync(&sbd);
 }
@@ -718,20 +807,36 @@ int parse_rindex(struct gfs2_inode *di, int print_rindex)
 {
 	int error, start_line;
 	struct gfs2_rindex ri;
-	char buf[sizeof(struct gfs2_rindex)];
+	char buf[sizeof(struct gfs_rindex)];
 	char highlighted_addr[32];
 
 	start_line = line;
 	error = 0;
-	print_gfs2("RG index entries found: %d.",
-			   di->i_di.di_size / sizeof(struct gfs2_rindex));
+	print_gfs2("RG index entries found: %d.", di->i_di.di_size / risize());
 	eol(0);
 	lines_per_row[dmode] = 6;
 	memset(highlighted_addr, 0, sizeof(highlighted_addr));
+	if (gfs1) {
+		/* gfs1 rindex files have the meta_header which is not
+		   accounted for in gfs2's dinode size.  Therefore, adjust. */
+		di->i_di.di_size += ((di->i_di.di_size / sbd.bsize) + 1) *
+			sizeof(struct gfs2_meta_header);
+	}
 	for (print_entry_ndx=0; ; print_entry_ndx++) {
-		error = gfs2_readi(di, (void *)&buf,
-				   print_entry_ndx * sizeof(struct gfs2_rindex),
-				   sizeof(struct gfs2_rindex));
+		uint64_t gfs1_adj = 0;
+		uint64_t offset = print_entry_ndx * risize();
+
+		if (gfs1) {
+			uint64_t sd_jbsize =
+				(sbd.bsize - sizeof(struct gfs2_meta_header));
+
+			gfs1_adj = (offset / sd_jbsize) *
+				sizeof(struct gfs2_meta_header);
+			gfs1_adj += sizeof(struct gfs2_meta_header);
+		}
+
+		error = gfs2_readi(di, (void *)&buf, offset + gfs1_adj,
+				   risize());
 		if (!error) /* end of file */
 			break;
 		gfs2_rindex_in(&ri, buf);
@@ -753,12 +858,18 @@ int parse_rindex(struct gfs2_inode *di, int print_rindex)
 			if(print_rindex)
 				gfs2_rindex_print(&ri);
 			else {
-				struct gfs2_rgrp rg;
 				struct gfs2_buffer_head *tmp_bh;
 
 				tmp_bh = bread(&sbd, ri.ri_addr);
-				gfs2_rgrp_in(&rg, tmp_bh->b_data);
-				gfs2_rgrp_print(&rg);
+				if (gfs1) {
+					struct gfs_rgrp rg1;
+					gfs_rgrp_in(&rg1, tmp_bh->b_data);
+					gfs_rgrp_print(&rg1);
+				} else {
+					struct gfs2_rgrp rg;
+					gfs2_rgrp_in(&rg, tmp_bh->b_data);
+					gfs2_rgrp_print(&rg);
+				}
 				brelse(tmp_bh, not_updated);
 			}
 			last_entry_onscreen[dmode] = print_entry_ndx;
@@ -1058,8 +1169,8 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 				diptrs = 483;
 				inptrs = 501;
 			} else {
-				diptrs = (bufsize - sizeof(sizeof(struct gfs2_dinode))) / sizeof(uint64_t);
-				inptrs = (bufsize - sizeof(sizeof(struct gfs2_meta_header))) /
+				diptrs = (sbd.bsize - sizeof(sizeof(struct gfs2_dinode))) / sizeof(uint64_t);
+				inptrs = (sbd.bsize - sizeof(sizeof(struct gfs2_meta_header))) /
 					sizeof(uint64_t);
 			}
 			/* Multiply out the max factor based on inode height.*/
@@ -1126,7 +1237,7 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 			offsets[0] = pndx;
 			for (hgt = cur_height; hgt >= 0; hgt--)
 				file_offset += offsets[cur_height - hgt] *
-					factor[di.di_height - hgt - 1] * bufsize;
+					factor[di.di_height - hgt - 1] * sbd.bsize;
 			print_gfs2("     ");
 			h = 'K';
 			human_off = (file_offset / 1024.0);
@@ -1148,12 +1259,12 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 			char *tmpbuf;
 			
 			more_indir = malloc(sizeof(struct iinfo));
-			tmpbuf = malloc(bufsize);
+			tmpbuf = malloc(sbd.bsize);
 			if (tmpbuf) {
 				do_lseek(sbd.device_fd,
-					 ind->ii[pndx].block * bufsize);
+					 ind->ii[pndx].block * sbd.bsize);
 				do_read(sbd.device_fd, tmpbuf,
-					bufsize); /* read in the desired block */
+					sbd.bsize); /* read in the desired block */
 				memset(more_indir, 0, sizeof(struct iinfo));
 				if (S_ISDIR(di.di_mode)) {
 					do_leaf_extended(tmpbuf, more_indir);
@@ -1283,7 +1394,10 @@ int display_extended(void)
 	else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
 		return -1;
 	else if (block_is_rglist()) {
-		tmp_bh = bread(&sbd, masterblock("rindex"));
+		if (gfs1)
+			tmp_bh = bread(&sbd, sbd1->sb_rindex_di.no_addr);
+		else
+			tmp_bh = bread(&sbd, masterblock("rindex"));
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		parse_rindex(tmp_inode, FALSE);
 		brelse(tmp_bh, not_updated);
@@ -1325,7 +1439,7 @@ void read_superblock(int fd)
 	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
 	do_lseek(fd, 0x10 * 4096);
-	do_read(fd, buf, bufsize); /* read in the desired block */
+	do_read(fd, buf, sbd.bsize); /* read in the desired block */
 	memset(&sbd, 0, sizeof(struct gfs2_sbd));
 	sbd.device_fd = fd;
 	sbd.bsize = GFS2_DEFAULT_BSIZE;
@@ -1354,10 +1468,11 @@ void read_superblock(int fd)
 	}
 	else
 		gfs1 = FALSE;
-	bufsize = sbd.sd_sb.sb_bsize;
-	if (!bufsize)
-		bufsize = GFS2_DEFAULT_BSIZE;
-	block = 0x10 * (GFS2_DEFAULT_BSIZE / bufsize);
+	sbd.bsize = sbd.sd_sb.sb_bsize;
+	if (!sbd.bsize)
+		sbd.bsize = GFS2_DEFAULT_BSIZE;
+	compute_constants(&sbd);
+	block = 0x10 * (GFS2_DEFAULT_BSIZE / sbd.bsize);
 }
 
 /* ------------------------------------------------------------------------ */
@@ -1366,8 +1481,8 @@ void read_superblock(int fd)
 void read_master_dir(void)
 {
 	ioctl(sbd.device_fd, BLKFLSBUF, 0);
-	do_lseek(sbd.device_fd, sbd.sd_sb.sb_master_dir.no_addr * bufsize);
-	do_read(sbd.device_fd, buf, bufsize); /* read in the desired block */
+	do_lseek(sbd.device_fd, sbd.sd_sb.sb_master_dir.no_addr * sbd.bsize);
+	do_read(sbd.device_fd, buf, sbd.bsize); /* read in the desired block */
 	gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
 	do_dinode_extended(&di, buf); /* get extended data, if any */
 	memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
@@ -1380,19 +1495,22 @@ int display(int identify_only)
 {
 	uint64_t blk;
 
-	if (block == RGLIST_DUMMY_BLOCK)
-		blk = masterblock("rindex");
-	else
+	if (block == RGLIST_DUMMY_BLOCK) {
+		if (gfs1)
+			blk = sbd1->sb_rindex_di.no_addr;
+		else
+			blk = masterblock("rindex");
+	} else
 		blk = block;
 	if (termlines) {
 		display_title_lines();
 		move(2,0);
 	}
 	if (block_in_mem != blk) { /* If we changed blocks from the last read */
-		dev_offset = blk * bufsize;
+		dev_offset = blk * sbd.bsize;
 		ioctl(sbd.device_fd, BLKFLSBUF, 0);
 		do_lseek(sbd.device_fd, dev_offset);
-		do_read(sbd.device_fd, buf, bufsize); /* read desired block */
+		do_read(sbd.device_fd, buf, sbd.bsize); /* read desired block */
 		block_in_mem = blk; /* remember which block is in memory */
 	}
 	line = 1;
@@ -1401,7 +1519,7 @@ int display(int identify_only)
 		return 0;
 	indirect_blocks = 0;
 	lines_per_row[dmode] = 1;
-	if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / bufsize)) {
+	if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / sbd.bsize)) {
 		gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */
 		memset(indirect, 0, sizeof(indirect));
 		indirect->ii[0].block = sbd.sd_sb.sb_master_dir.no_addr;
@@ -1450,7 +1568,7 @@ int display(int identify_only)
 	if (dmode == HEX_MODE)          /* if hex display mode           */
 		hexdump(dev_offset, buf,
 			(gfs2_struct_type == GFS2_METATYPE_DI)?
-			struct_len + di.di_size:bufsize);
+			struct_len + di.di_size:sbd.bsize);
 	else if (dmode == GFS2_MODE)    /* if structure display          */
 		display_gfs2();            /* display the gfs2 structure    */
 	else
@@ -1508,6 +1626,65 @@ uint64_t pop_block(void)
 }
 
 /* ------------------------------------------------------------------------ */
+/* Check if the word is a keyword such as "sb" or "rindex"                  */
+/* Returns: block number if it is, else 0                                   */
+/* ------------------------------------------------------------------------ */
+uint64_t check_keywords(const char *kword)
+{
+	uint64_t blk = 0;
+
+	if (!strcmp(kword, "sb") ||!strcmp(kword, "superblock"))
+		blk = 0x10 * (4096 / sbd.bsize); /* superblock */
+	else if (!strcmp(kword, "root") || !strcmp(kword, "rootdir"))
+		blk = sbd.sd_sb.sb_root_dir.no_addr;
+	else if (!strcmp(kword, "master")) {
+		if (!gfs1)
+			blk = sbd.sd_sb.sb_master_dir.no_addr;
+		else
+			fprintf(stderr, "This is GFS1; there's no master directory.\n");
+	}
+	else if (!strcmp(kword, "jindex")) {
+		if (gfs1)
+			blk = sbd1->sb_jindex_di.no_addr;
+		else
+			blk = masterblock("jindex"); /* journal index */
+	}
+	else if (!gfs1 && !strcmp(kword, "per_node"))
+		blk = masterblock("per_node");
+	else if (!gfs1 && !strcmp(kword, "inum"))
+		blk = masterblock("inum");
+	else if (!strcmp(kword, "statfs")) {
+		if (gfs1)
+			blk = gfs1_license_di.no_addr;
+		else
+			blk = masterblock("statfs");
+	}
+	else if (!strcmp(kword, "rindex") || !strcmp(kword, "rgindex")) {
+		if (gfs1)
+			blk = sbd1->sb_rindex_di.no_addr;
+		else
+			blk = masterblock("rindex");
+	} else if (!strcmp(kword, "rgs")) {
+		blk = RGLIST_DUMMY_BLOCK;
+	} else if (!strcmp(kword, "quota")) {
+		if (gfs1)
+			blk = gfs1_quota_di.no_addr;
+		else
+			blk = masterblock("quota");
+	} else if (!strncmp(kword, "rg ", 3)) {
+		int rgnum = 0;
+
+		rgnum = atoi(kword + 3);
+		blk = get_rg_addr(rgnum);
+	} else if (kword[0]=='0' && kword[1]=='x') /* hex addr */
+		sscanf(kword, "%"SCNx64, &blk);/* retrieve in hex */
+	else
+		sscanf(kword, "%" PRIu64, &blk); /* retrieve decimal */
+
+	return blk;
+}
+
+/* ------------------------------------------------------------------------ */
 /* goto_block - go to a desired block entered by the user                   */
 /* ------------------------------------------------------------------------ */
 uint64_t goto_block(void)
@@ -1518,30 +1695,8 @@ uint64_t goto_block(void)
 	memset(string, 0, sizeof(string));
 	sprintf(string,"%"PRId64, block);
 	if (bobgets(string, 1, 7, 16, &ch)) {
-		if (!strcmp(string,"root"))
-			temp_blk = sbd.sd_sb.sb_root_dir.no_addr;
-		else if (!strcmp(string,"master")) {
-			if (!gfs1)
-				temp_blk = sbd.sd_sb.sb_master_dir.no_addr;
-			else
-				; /* maybe put out an error message at some point */
-		}
-		else if (isalpha(string[0])) {
-			if (gfs1) {
-				if (!strcmp(string, "jindex"))
-					temp_blk = sbd1->sb_jindex_di.no_addr;
-				else if (!strcmp(string, "rindex"))
-					temp_blk = sbd1->sb_rindex_di.no_addr;
-				else if (!strcmp(string, "quota"))
-					temp_blk = gfs1_quota_di.no_addr;
-			}
-			else {
-				if (!strcmp(string, "rgs"))
-					temp_blk = RGLIST_DUMMY_BLOCK;
-				else
-					temp_blk = masterblock(string);
-			}
-		}
+		if (isalnum(string[0]))
+			temp_blk = check_keywords(string);
 		else if (string[0] == '+') {
 			if (string[1] == '0' && string[2] == 'x')
 				sscanf(string, "%"SCNx64, &temp_blk);
@@ -1556,10 +1711,6 @@ uint64_t goto_block(void)
 				sscanf(string, "%" PRIu64, &temp_blk);
 			temp_blk -= block;
 		}
-		else if (string[0] == '0' && string[1] == 'x')
-			sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
-		else
-			sscanf(string, "%" PRIu64, &temp_blk); /* retrieve decimal */
 
 		if (temp_blk == RGLIST_DUMMY_BLOCK || temp_blk < max_block) {
 			offset = 0;
@@ -1604,7 +1755,7 @@ void hex_edit(int *exitch)
 	int left_off;
 	int ch;
 
-	left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17;
+	left_off = ((block * sbd.bsize) < 0xffffffff) ? 9 : 17;
 	/* 8 and 16 char addresses on screen */
 	
 	if (bobgets(estring, edit_row[dmode] + 3,
@@ -1637,7 +1788,7 @@ void hex_edit(int *exitch)
 				buf[offset + hexoffset] = ch;
 			}
 			do_lseek(sbd.device_fd, dev_offset);
-			do_write(sbd.device_fd, buf, bufsize);
+			do_write(sbd.device_fd, buf, sbd.bsize);
 			fsync(sbd.device_fd);
 		}
 	}
@@ -1665,10 +1816,10 @@ void pageup(void)
 		if (dmode == GFS2_MODE || offset==0) {
 			block--;
 			if (dmode == HEX_MODE)
-				offset = (bufsize % screen_chunk_size) > 0 ? 
+				offset = (sbd.bsize % screen_chunk_size) > 0 ?
 					screen_chunk_size *
-					(bufsize / screen_chunk_size) :
-					bufsize - screen_chunk_size;
+					(sbd.bsize / screen_chunk_size) :
+					sbd.bsize - screen_chunk_size;
 			else
 				offset = 0;
 		}
@@ -1696,7 +1847,7 @@ void pagedn(void)
 	else {
 		start_row[dmode] = edit_row[dmode] = 0;
 		if (dmode == GFS2_MODE ||
-		    offset + screen_chunk_size >= bufsize) {
+		    offset + screen_chunk_size >= sbd.bsize) {
 			block++;
 			offset = 0;
 		}
@@ -1802,7 +1953,7 @@ void interactive_mode(void)
 				edit_row[dmode] = 0;
 			}
 			else {
-				block = 0x10 * (4096 / bufsize);
+				block = 0x10 * (4096 / sbd.bsize);
 				push_block(block);
 				offset = 0;
 			}
@@ -2033,7 +2184,7 @@ void dump_journal(const char *journal)
 	uint64_t jindex_block, jblock, j_size, jb;
 	int error, start_line, journal_num;
 	struct gfs2_dinode jdi;
-	char jbuf[bufsize];
+	char jbuf[sbd.bsize];
 	struct gfs2_inode *j_inode = NULL;
 
 	start_line = line;
@@ -2077,16 +2228,16 @@ void dump_journal(const char *journal)
 		j_size = jdi.di_size;
 	}
 
-	for (jb = 0; jb < j_size; jb += (gfs1 ? 1:bufsize)) {
+	for (jb = 0; jb < j_size; jb += (gfs1 ? 1:sbd.bsize)) {
 		if (gfs1) {
 			if (j_bh)
 				brelse(j_bh, not_updated);
 			j_bh = bread(&sbd, jblock + jb);
-			memcpy(jbuf, j_bh->b_data, bufsize);
+			memcpy(jbuf, j_bh->b_data, sbd.bsize);
 		}
 		else
 			error = gfs2_readi(j_inode, (void *)&jbuf, jb,
-					   bufsize);
+					   sbd.bsize);
 		if (!error) /* end of file */
 			break;
 		if (get_block_type(jbuf) == GFS2_METATYPE_LD) {
@@ -2111,7 +2262,7 @@ void dump_journal(const char *journal)
 				 "Quota", "Final Entry", "Unknown"}};
 
 			print_gfs2("Block #%4llx: Log descriptor, ",
-				   jb / (gfs1 ? 1 : bufsize));
+				   jb / (gfs1 ? 1 : sbd.bsize));
 			gfs2_log_descriptor_in(&ld, jbuf);
 			print_gfs2("type %d ", ld.ld_type);
 
@@ -2131,7 +2282,7 @@ void dump_journal(const char *journal)
 			else
 				b = (uint64_t *)(jbuf +
 					sizeof(struct gfs2_log_descriptor));
-			while (*b && (char *)b < (jbuf + bufsize)) {
+			while (*b && (char *)b < (jbuf + sbd.bsize)) {
 				if (!termlines ||
 				    (print_entry_ndx >= start_row[dmode] &&
 				     ((print_entry_ndx - start_row[dmode])+1) *
@@ -2152,16 +2303,17 @@ void dump_journal(const char *journal)
 
 			if (gfs1) {
 				gfs_log_header_in(&lh1, jbuf);
-				print_gfs2("Block #%4llx: Log header: Seq"
-					   "= 0x%x, first = 0x%x tail = "
-					   "0x%x, last = 0x%x",
-					   jb, lh1.lh_sequence, lh1.lh_first,
-					   lh1.lh_tail, lh1.lh_last_dump);
+				print_gfs2("Block #%4llx: Log header: Flags = "
+					   "%08x, Seq = 0x%x, first = 0x%x "
+					   "tail = 0x%x, last = 0x%x",
+					   jb, lh1.lh_flags, lh1.lh_sequence,
+					   lh1.lh_first, lh1.lh_tail,
+					   lh1.lh_last_dump);
 			} else {
 				gfs2_log_header_in(&lh, jbuf);
 				print_gfs2("Block #%4llx: Log header: Seq"
 					   "= 0x%x, tail = 0x%x, blk = 0x%x",
-					   jb / bufsize, lh.lh_sequence,
+					   jb / sbd.bsize, lh.lh_sequence,
 					   lh.lh_tail, lh.lh_blkno);
 			}
 			eol(0);
@@ -2183,6 +2335,7 @@ void usage(void)
 	fprintf(stderr,"savemeta <file_system> <file> - save off your metadata for analysis and debugging.\n");
 	fprintf(stderr,"   (The intelligent way: assume bitmap is correct).\n");
 	fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging.  The SLOW way (block by block).\n");
+	fprintf(stderr,"savergs - save off only the resource group information (rindex and rgs).\n");
 	fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
 	fprintf(stderr,"rgcount - print how many RGs in the file system.\n");
 	fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
@@ -2201,6 +2354,7 @@ void usage(void)
 	fprintf(stderr,"     rg X - print resource group X.\n");
 	fprintf(stderr,"     rgs - prints all the resource groups (rgs).\n");
 	fprintf(stderr,"     quota - prints the quota file.\n");
+	fprintf(stderr,"-s   specifies a starting block such as root, rindex, quota, inum.\n");
 	fprintf(stderr,"-x   print in hexmode.\n");
 	fprintf(stderr,"-h   prints this help.\n\n");
 	fprintf(stderr,"Examples:\n");
@@ -2261,6 +2415,8 @@ void process_parameters(int argc, char *argv[], int pass)
 				termlines = 0;
 			else if (!strcasecmp(argv[i], "savemetaslow"))
 				termlines = 0;
+			else if (!strcasecmp(argv[i], "savergs"))
+				termlines = 0;
 			else if (!strcasecmp(argv[i], "printsavedmeta"))
 				restoremeta(argv[i+1], argv[i+2],
 					    TRUE);
@@ -2276,8 +2432,25 @@ void process_parameters(int argc, char *argv[], int pass)
 				strcpy(device, argv[i]);
 		}
 		else { /* second pass */
-			if (!termlines && !strchr(argv[i],'/')) { /* if print, no slash */
-				if (!strcasecmp(argv[i], "-x"))
+			if (!strcasecmp(argv[i], "-s")) {
+				i++;
+				if (i >= argc - 1) {
+					printf("Error: starting block not specified with -s.\n");
+					printf("%s -s [starting block | keyword] <device>\n",
+					       argv[0]);
+					printf("For example: %s -s \"rg 3\" /dev/exxon_vg/exxon_lv\n",
+					       argv[0]);
+					exit(EXIT_FAILURE);
+				}
+				starting_blk = check_keywords(argv[i]);
+			}
+			else if (!termlines && !strchr(argv[i],'/')) { /* if print, no slash */
+				uint64_t keyword_blk;
+
+				keyword_blk = check_keywords(argv[i]);
+				if (keyword_blk)
+					push_block(keyword_blk);
+				else if (!strcasecmp(argv[i], "-x"))
 					dmode = HEX_MODE;
 				else if (argv[i][0] == '-') /* if it starts with a dash */
 					; /* ignore it--meant for pass == 0 */
@@ -2286,47 +2459,6 @@ void process_parameters(int argc, char *argv[], int pass)
 				else if (!strcmp(argv[i], "size"))
 					printf("Device size: %" PRIu64 " (0x%" PRIx64 ")\n",
 						   max_block, max_block);
-				else if (!strcmp(argv[i], "sb") ||
-						 !strcmp(argv[i], "superblock"))
-					push_block(0x10 * (4096 / bufsize)); /* superblock */
-				else if (!strcmp(argv[i], "root") ||
-						 !strcmp(argv[i], "rootdir"))
-					push_block(sbd.sd_sb.sb_root_dir.no_addr);
-				else if (!strcmp(argv[i], "master")) {
-					if (!gfs1)
-						push_block(sbd.sd_sb.sb_master_dir.no_addr);
-					else
-						fprintf(stderr, "This is GFS1; there's no master directory.\n");
-				}
-				else if (!strcmp(argv[i], "jindex")) {
-					if (gfs1)
-						push_block(sbd1->sb_jindex_di.no_addr);
-					else
-						push_block(masterblock("jindex"));/* journal index */
-				}
-				else if (!gfs1 && !strcmp(argv[i], "per_node"))
-					push_block(masterblock("per_node"));
-				else if (!gfs1 && !strcmp(argv[i], "inum"))
-					push_block(masterblock("inum"));
-				else if (!gfs1 && !strcmp(argv[i], "statfs"))
-					push_block(masterblock("statfs"));
-				else if (!strcmp(argv[i], "rindex") ||
-						 !strcmp(argv[i], "rgindex")) {
-					if (gfs1)
-						push_block(sbd1->sb_rindex_di.no_addr);
-					else
-						push_block(masterblock("rindex"));
-				}
-				else if (!strcmp(argv[i], "rgs")) {
-					if (!gfs1)
-						push_block(RGLIST_DUMMY_BLOCK);
-				}
-				else if (!strcmp(argv[i], "quota")) {
-					if (gfs1)
-						push_block(gfs1_quota_di.no_addr);
-					else
-						push_block(masterblock("quota"));
-				}
 				else if (!strcmp(argv[i], "rgcount"))
 					rgcount();
 				else if (!strcmp(argv[i], "rgflags")) {
@@ -2379,13 +2511,11 @@ void process_parameters(int argc, char *argv[], int pass)
 					exit(EXIT_SUCCESS);
 				}
 				else if (!strcasecmp(argv[i], "savemeta"))
-					savemeta(argv[i+2], FALSE);
+					savemeta(argv[i+2], 0);
 				else if (!strcasecmp(argv[i], "savemetaslow"))
-					savemeta(argv[i+2], TRUE);
-				else if (argv[i][0]=='0' && argv[i][1]=='x') { /* hex addr */
-					sscanf(argv[i], "%"SCNx64, &temp_blk);/* retrieve in hex */
-					push_block(temp_blk);
-				}
+					savemeta(argv[i+2], 1);
+				else if (!strcasecmp(argv[i], "savergs"))
+					savemeta(argv[i+2], 2);
 				else if (isdigit(argv[i][0])) { /* decimal addr */
 					sscanf(argv[i], "%"SCNd64, &temp_blk);
 					push_block(temp_blk);
@@ -2431,8 +2561,9 @@ int main(int argc, char *argv[])
 	memset(edit_size, 0, sizeof(edit_size));
 	memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
 	dmode = HEX_MODE;
-	type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */
-	block = 0x10;
+	sbd.bsize = 4096;
+	type_alloc(buf, char, sbd.bsize); /* allocate/malloc a new 4K buffer */
+	block = starting_blk = 0x10;
 	for (i = 0; i < BLOCK_STACK_SIZE; i++) {
 		blockstack[i].dmode = dmode;
 		blockstack[i].block = block;
@@ -2454,15 +2585,17 @@ int main(int argc, char *argv[])
 	fd = open(device, O_RDWR);
 	if (fd < 0)
 		die("can't open %s: %s\n", device, strerror(errno));
-	max_block = lseek(fd, 0, SEEK_END) / bufsize;
+	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
 
 	read_superblock(fd);
+	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
 	strcpy(sbd.device_name, device);
 	if (!gfs1)
 		read_master_dir();
 	block_in_mem = -1;
-	if (!termlines)    /* if printing to stdout */
-		process_parameters(argc, argv, 1); /* get what to print from cmdline */
+	process_parameters(argc, argv, 1); /* get what to print from cmdline */
+
+	block = blockstack[0].block = starting_blk * (4096 / sbd.bsize);
 
 	if (termlines)
 		interactive_mode();
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 4778ab1..40d1d58 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -74,7 +74,6 @@ EXTERN char estring[1024]; /* edit string */
 EXTERN uint64_t dev_offset INIT(0);
 EXTERN uint64_t max_block INIT(0);
 EXTERN char *buf INIT(NULL);
-EXTERN uint64_t bufsize INIT(4096);
 EXTERN int termlines INIT(30);
 EXTERN int termcols INIT(80);
 EXTERN int insert INIT(0);
@@ -101,6 +100,7 @@ EXTERN WINDOW *wind;
 EXTERN int gfs1 INIT(0);
 EXTERN int editing INIT(0);
 EXTERN uint64_t temp_blk;
+EXTERN uint64_t starting_blk;
 
 struct gfs_jindex {
         uint64_t ji_addr;       /* starting block of the journal */
@@ -135,6 +135,38 @@ struct gfs_log_header {
 	char lh_reserved[64];
 };
 
+struct gfs_rindex {
+	uint64_t ri_addr;     /* block # of 1st block (header) in rgrp */
+	uint32_t ri_length;   /* # fs blocks containing rgrp header & bitmap */
+	uint32_t ri_pad;
+
+	uint64_t ri_data1;    /* block # of first data/meta block in rgrp */
+	uint32_t ri_data;     /* number (qty) of data/meta blocks in rgrp */
+
+	uint32_t ri_bitbytes; /* total # bytes used by block alloc bitmap */
+
+	char ri_reserved[64];
+};
+
+struct gfs_rgrp {
+	struct gfs2_meta_header rg_header;
+
+	uint32_t rg_flags;      /* ?? */
+
+	uint32_t rg_free;       /* Number (qty) of free data blocks */
+
+	/* Dinodes are USEDMETA, but are handled separately from other METAs */
+	uint32_t rg_useddi;     /* Number (qty) of dinodes (used or free) */
+	uint32_t rg_freedi;     /* Number (qty) of unused (free) dinodes */
+	struct gfs2_inum rg_freedi_list; /* 1st block in chain of free dinodes */
+
+	/* These META statistics do not include dinodes (used or free) */
+	uint32_t rg_usedmeta;   /* Number (qty) of used metadata blocks */
+	uint32_t rg_freemeta;   /* Number (qty) of unused metadata blocks */
+
+	char rg_reserved[64];
+};
+
 EXTERN int block_is_jindex(void);
 EXTERN int block_is_rindex(void);
 EXTERN int block_is_inum_file(void);
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index c73dc09..cff2f30 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -49,6 +49,7 @@ struct saved_metablock *savedata;
 uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
 struct gfs2_block_list *blocklist = NULL;
 uint64_t journal_blocks[MAX_JOURNALS_SAVED];
+uint64_t gfs1_journal_size = 0; /* in blocks */
 int journals_found = 0;
 
 extern void read_superblock(void);
@@ -383,7 +384,7 @@ int get_gfs_struct_info(char *buf, int *block_type, int *struct_len)
 	struct gfs2_meta_header mh;
 
 	*block_type = 0;
-	*struct_len = bufsize;
+	*struct_len = sbd.bsize;
 
 	gfs2_meta_header_in(&mh, buf);
 	if (mh.mh_magic != GFS2_MAGIC)
@@ -396,19 +397,19 @@ int get_gfs_struct_info(char *buf, int *block_type, int *struct_len)
 		*struct_len = sizeof(struct gfs_sb);
 		break;
 	case GFS2_METATYPE_RG:   /* 2 (rsrc grp hdr) */
-		*struct_len = bufsize; /*sizeof(struct gfs_rgrp);*/
+		*struct_len = sbd.bsize; /*sizeof(struct gfs_rgrp);*/
 		break;
 	case GFS2_METATYPE_RB:   /* 3 (rsrc grp bitblk) */
-		*struct_len = bufsize;
+		*struct_len = sbd.bsize;
 		break;
 	case GFS2_METATYPE_DI:   /* 4 (disk inode) */
-		*struct_len = bufsize; /*sizeof(struct gfs_dinode);*/
+		*struct_len = sbd.bsize; /*sizeof(struct gfs_dinode);*/
 		break;
 	case GFS2_METATYPE_IN:   /* 5 (indir inode blklst) */
-		*struct_len = bufsize; /*sizeof(struct gfs_indirect);*/
+		*struct_len = sbd.bsize; /*sizeof(struct gfs_indirect);*/
 		break;
 	case GFS2_METATYPE_LF:   /* 6 (leaf dinode blklst) */
-		*struct_len = bufsize; /*sizeof(struct gfs_leaf);*/
+		*struct_len = sbd.bsize; /*sizeof(struct gfs_leaf);*/
 		break;
 	case GFS2_METATYPE_JD:   /* 7 (journal data) */
 		*struct_len = sizeof(struct gfs2_meta_header);
@@ -417,16 +418,16 @@ int get_gfs_struct_info(char *buf, int *block_type, int *struct_len)
 		*struct_len = sizeof(struct gfs2_log_header);
 		break;
 	case GFS2_METATYPE_LD:   /* 9 (log descriptor) */
-		*struct_len = bufsize;
+		*struct_len = sbd.bsize;
 		break;
 	case GFS2_METATYPE_EA:   /* 10 (extended attr hdr) */
-		*struct_len = bufsize;
+		*struct_len = sbd.bsize;
 		break;
 	case GFS2_METATYPE_ED:   /* 11 (extended attr data) */
-		*struct_len = bufsize;
+		*struct_len = sbd.bsize;
 		break;
 	default:
-		*struct_len = bufsize;
+		*struct_len = sbd.bsize;
 		break;
 	}
 	return 0;
@@ -509,8 +510,8 @@ int save_block(int fd, int out_fd, uint64_t blk)
 		return 0;
 	}
 	memset(savedata, 0, sizeof(struct saved_metablock));
-	do_lseek(fd, blk * bufsize);
-	do_read(fd, savedata->buf, bufsize); /* read in the block */
+	do_lseek(fd, blk * sbd.bsize);
+	do_read(fd, savedata->buf, sbd.bsize); /* read in the block */
 
 	/* If this isn't metadata and isn't a system file, we don't want it.
 	   Note that we're checking "block" here rather than blk.  That's
@@ -522,7 +523,7 @@ int save_block(int fd, int out_fd, uint64_t blk)
 		return 0; /* Not metadata, and not system file, so skip it */
 	trailing0 = 0;
 	p = &savedata->buf[blklen - 1];
-	while (*p=='\0' && trailing0 < bufsize) {
+	while (*p=='\0' && trailing0 < sbd.bsize) {
 		trailing0++;
 		p--;
 	}
@@ -597,7 +598,7 @@ void save_inode_data(int out_fd)
 
 	for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
 		osi_list_init(&metalist[i]);
-	buf = malloc(bufsize);
+	buf = malloc(sbd.bsize);
 	metabh = bread(&sbd, block);
 	inode = inode_get(&sbd, metabh);
 	height = inode->i_di.di_height;
@@ -631,7 +632,7 @@ void save_inode_data(int out_fd)
 	/* Process directory exhash inodes */
 	if (S_ISDIR(inode->i_di.di_mode)) {
 		if (inode->i_di.di_flags & GFS2_DIF_EXHASH) {
-			save_indirect_blocks(out_fd, cur_list, mybh,
+			save_indirect_blocks(out_fd, cur_list, metabh,
 					     height, 0);
 		}
 	}
@@ -645,7 +646,7 @@ void save_inode_data(int out_fd)
 		gfs2_meta_header_in(&mh, metabh->b_data);
 		if (mh.mh_magic == GFS2_MAGIC) {
 			for (e = sizeof(struct gfs2_meta_header);
-			     e < bufsize; e += ea.ea_rec_len) {
+			     e < sbd.bsize; e += ea.ea_rec_len) {
 				uint64_t blk, *b;
 				int charoff;
 
@@ -701,7 +702,9 @@ void get_journal_inode_blocks(void)
 			struct gfs_jindex ji;
 			char jbuf[sizeof(struct gfs_jindex)];
 
+			bh = bread(&sbd, sbd1->sb_jindex_di.no_addr);
 			j_inode = inode_get(&sbd, bh);
+			brelse(bh, not_updated);
 			amt = gfs2_readi(j_inode, (void *)&jbuf,
 					 journal * sizeof(struct gfs_jindex),
 					 sizeof(struct gfs_jindex));
@@ -709,7 +712,7 @@ void get_journal_inode_blocks(void)
 				break;
 			gfs_jindex_in(&ji, jbuf);
 			jblock = ji.ji_addr;
-			inode_put(j_inode, not_updated);
+			gfs1_journal_size = ji.ji_nsegment * 16;
 		} else {
 			if (journal > indirect->ii[0].dirents - 3)
 				break;
@@ -723,15 +726,17 @@ void get_journal_inode_blocks(void)
 	}
 }
 
-void savemeta(const char *out_fn, int slow)
+void savemeta(const char *out_fn, int saveoption)
 {
 	int out_fd;
+	int slow;
 	osi_list_t *tmp;
 	uint64_t memreq;
 	int rgcount;
 	uint64_t jindex_block;
 	struct gfs2_buffer_head *bh;
 
+	slow = (saveoption == 1);
 	sbd.md.journals = 1;
 
 	if (!out_fn)
@@ -748,7 +753,7 @@ void savemeta(const char *out_fn, int slow)
 
 	do_lseek(sbd.device_fd, 0);
 	blks_saved = total_out = last_reported_block = 0;
-	bufsize = BUFSIZE;
+	sbd.bsize = BUFSIZE;
 	if (!slow) {
 		int i;
 
@@ -760,14 +765,14 @@ void savemeta(const char *out_fn, int slow)
 			osi_list_init(&sbd.buf_hash[i]);
 		sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
 		compute_constants(&sbd);
-		if(read_sb(&sbd) < 0)
+		if(!gfs1 && read_sb(&sbd) < 0)
 			slow = TRUE;
 		else
-			bufsize = sbd.bsize = sbd.sd_sb.sb_bsize;
+			sbd.bsize = sbd.bsize = sbd.sd_sb.sb_bsize;
 	}
-	last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / bufsize;
-	printf("There are %" PRIu64 " blocks of %" PRIu64 " bytes.\n",
-	       last_fs_block, bufsize);
+	last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / sbd.bsize;
+	printf("There are %" PRIu64 " blocks of %u bytes.\n",
+	       last_fs_block, sbd.bsize);
 	if (!slow) {
 		if (gfs1) {
 			sbd.md.riinode =
@@ -807,7 +812,25 @@ void savemeta(const char *out_fn, int slow)
 	get_journal_inode_blocks();
 	if (!slow) {
 		/* Save off the superblock */
-		save_block(sbd.device_fd, out_fd, 0x10 * (4096 / bufsize));
+		save_block(sbd.device_fd, out_fd, 0x10 * (4096 / sbd.bsize));
+		/* If this is gfs1, save off the rindex because it's not
+		   part of the file system as it is in gfs2. */
+		if (gfs1) {
+			int j;
+
+			block = sbd1->sb_rindex_di.no_addr;
+			save_block(sbd.device_fd, out_fd, block);
+			save_inode_data(out_fd);
+			/* In GFS1, journals aren't part of the RG space */
+			for (j = 0; j < journals_found; j++) {
+				log_debug("Saving journal #%d\n", j + 1);
+				for (block = journal_blocks[j];
+				     block < journal_blocks[j] +
+					     gfs1_journal_size;
+				     block++)
+					save_block(sbd.device_fd, out_fd, block);
+			}
+		}
 		/* Walk through the resource groups saving everything within */
 		for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
 		     tmp = tmp->next){
@@ -834,15 +857,17 @@ void savemeta(const char *out_fn, int slow)
 				save_block(sbd.device_fd, out_fd, block);
 			}
 			/* Save off the other metadata: inodes, etc. */
-			while (!gfs2_next_rg_meta(rgd, &block, first)) {
-				int blktype;
-
-				warm_fuzzy_stuff(block, FALSE, TRUE);
-				blktype = save_block(sbd.device_fd, out_fd,
-						     block);
-				if (blktype == GFS2_METATYPE_DI)
-					save_inode_data(out_fd);
-				first = 0;
+			if (saveoption != 2) {
+				while (!gfs2_next_rg_meta(rgd, &block, first)) {
+					int blktype;
+
+					warm_fuzzy_stuff(block, FALSE, TRUE);
+					blktype = save_block(sbd.device_fd,
+							     out_fd, block);
+					if (blktype == GFS2_METATYPE_DI)
+						save_inode_data(out_fd);
+					first = 0;
+				}
 			}
 			gfs2_rgrp_relse(rgd, not_updated);
 		}
@@ -886,7 +911,7 @@ int restore_data(int fd, int in_fd, int printblocksonly)
 			fprintf(stderr, "Error reading from file.\n");
 			return -1;
 		}
-		total_out += bufsize;
+		total_out += sbd.bsize;
 		savedata->blk = be64_to_cpu(buf64);
 		if (!printblocksonly &&
 		    last_fs_block && savedata->blk >= last_fs_block) {
@@ -918,15 +943,15 @@ int restore_data(int fd, int in_fd, int printblocksonly)
 					fprintf(stderr,"Error: Invalid superblock data.\n");
 					return -1;
 				}
-				bufsize = sbd.sd_sb.sb_bsize;
+				sbd.bsize = sbd.sd_sb.sb_bsize;
 				if (!printblocksonly) {
 					last_fs_block =
 						lseek(fd, 0, SEEK_END) /
-						bufsize;
-					printf("There are %" PRIu64 " blocks of %" \
-					       PRIu64 " bytes in the destination" \
+						sbd.bsize;
+					printf("There are %" PRIu64 " blocks of " \
+					       "%u bytes in the destination" \
 					       " file system.\n\n",
-					       last_fs_block, bufsize);
+					       last_fs_block, sbd.bsize);
 				}
 				first = 0;
 			}
@@ -942,8 +967,8 @@ int restore_data(int fd, int in_fd, int printblocksonly)
 					       "device; quitting.\n");
 					break;
 				}
-				do_lseek(fd, savedata->blk * bufsize);
-				do_write(fd, savedata->buf, bufsize);
+				do_lseek(fd, savedata->blk * sbd.bsize);
+				do_write(fd, savedata->buf, sbd.bsize);
 				writes++;
 			}
 			blks_saved++;
diff --git a/gfs2/man/gfs2_edit.8 b/gfs2/man/gfs2_edit.8
index 9e62eba..36a6018 100644
--- a/gfs2/man/gfs2_edit.8
+++ b/gfs2/man/gfs2_edit.8
@@ -44,6 +44,8 @@ You can specify the following data structure names with the -p option.
 
 \fIrindex\fR, \fIrgindex\fR - Print the resource group index system file.
 
+\fIrg X\fR - Print the resource group information for RG X (zero-based).
+
 \fIrgs\fR - Print the resource group information.
 
 \fIquota\fR - Print the contents of the system quota file.
@@ -71,6 +73,11 @@ For example, "gfs2_edit -p inum statfs /dev/sda1" prints the system inum
 file and the system statfs file on /dev/sda1.
 
 .TP
+\fB-p\fs [\fIstructure\fR | \fIblock\fR]
+Specify a starting block for interactive mode.  Any of the keywords found
+in the -p option may be specified.  If you want to start on a particular
+resource group, specify it in quotes, e.g. -p "rg 3"
+.TP
 \fB-h, -help, -usage\fP
 Print help information.
 .TP
@@ -85,6 +92,27 @@ Print program version information only.
 Print in hex mode.
 
 .TP
+\fBrg\fP \fI<rg>\fR \fI<device>\fR
+Print the contents of Resource Group \fI<rg>\fR on \fI<device>\fR.
+
+\fI<rg>\fR is a number from 0 to X - 1, where X is the number of RGs.
+.TP
+\fBrgcount\fP \fI<device>\fR
+Print the number of Resource Groups in the file system on \fI<device>\fR.
+.TP
+\fBrgflags\fP \fI<rg>\fR [\fInew_value\fR] \fI<device>\fR
+Print and/or modify the rg_flags value of Resource Group \fI<rg>\fR on
+\fI<device>\fR.
+
+\fI<rg>\fR is a number from 0 to X - 1, where X is the number of RGs.
+If \fInew_value\fR is not specified, the current rg_flags value will be
+printed but not modified.  If \fInew_value\fR is specified, the rg_flags
+field will be overwritten with the new value.
+.TP
+\fBprintsavedmeta\fP \fI<filename>\fR
+Print off a list of blocks from <filename> that were saved with the savemeta
+option.
+.TP
 \fBsavemeta\fP \fI<device>\fR \fI<filename>\fR
 Save off the GFS2 metadata (not user data) for the file system on the
 specified device to a file given by <filename>.  You can use this option
@@ -103,6 +131,10 @@ block in the file system for metadata.  This option is less prone to failure
 due to file system corruption than the savemeta option, but it is 
 extremely slow.
 .TP
+\fBsavergs\fP \fI<device>\fR \fI<filename>\fR
+Save off only the GFS2 resource group metadata for the file system on the
+specified device to a file given by <filename>.
+.TP
 \fBrestoremeta\fP \fI<filename>\fR \fI<dest device>\fR
 Take a file created with the savemeta option and restores its
 contents on top of the specified destination device.  \fBWARNING\fP:
@@ -128,7 +160,7 @@ You use the m key to switch between the modes, as described below.
 The modes are as follows:
 .TP
 Hex mode (default)
-Display or edits blocks of the file system in hexadecimal and ascii.
+Display or edit blocks of the file system in hexadecimal and ascii.
 
 Lines at the top indicate the currently displayed block in both hex and
 decimal.  If the block contains a GFS2 data structure, the name of that
@@ -267,8 +299,23 @@ Print the contents of block 16250 of /dev/sda1 in hex.
 gfs2_edit -p 12345 /dev/sdc2
 Print the gfs2 data structure at block 12345.
 
+.TP
+gfs2_edit rgcount /dev/sdb1
+Print how many Resource Groups exist for /dev/sdb1.
+
+.TP
+gfs2_edit -p rg 17 /dev/sdb1
+Print the contents of the eighteenth Resource Group on /dev/sdb1.
+
+.TP
+gfs2_edit rgflags 3 /dev/sdb1
+Print the rg_flags value for the fourth Resource Group on /dev/sdb1.
+
+.TP
+gfs2_edit rgflags 3 8 /dev/sdb1
+Set the GFS2_RGF_NOALLOC flag on for the fourth Resource Group on /dev/sdb1.
+
 .SH KNOWN BUGS
 .TP
 The directory code does not work well.  It might be confused
 by directory "sentinel" entries.
-


hooks/post-receive
--
Cluster Project



More information about the Cluster-cvs mailing list