This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cluster: RHEL55 - gfs2_edit -p block# shows wrong height/offset ongfs1 and segfaults on gfs2


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=90097fde5664cdb069920ee92d28b6461922cb18
Commit:        90097fde5664cdb069920ee92d28b6461922cb18
Parent:        fea471dc31137bb3c2583f369cf3af4a0e7eefcb
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Wed Sep 2 10:51:45 2009 -0500
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Wed Sep 2 10:51:45 2009 -0500

gfs2_edit -p block# shows wrong height/offset on gfs1 and segfaults on gfs2

The gfs2_edit tool was using crude calculations to try to figure out
indirect block offsets when showing and printing indirect blocks.
Those calculations have been switched to use "metapath" calculations
to take out the guesswork.

rhbz#506343
---
 gfs2/edit/gfs2hex.c |   16 +++++-
 gfs2/edit/gfs2hex.h |    4 ++
 gfs2/edit/hexedit.c |  150 +++++++++++++++++++++++++++++++++------------------
 gfs2/edit/hexedit.h |    3 +
 4 files changed, 118 insertions(+), 55 deletions(-)

diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index bb1c9eb..7f6790d 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -255,7 +255,7 @@ int indirect_dirent(struct indirect_info *indir, char *ptr, int d)
 ******************************************************************************/
 void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 {
-	unsigned int x, y;
+	unsigned int x, y, ptroff = 0;
 	uint64_t p, last;
 	int isdir = !!(S_ISDIR(di->di_mode)) || 
 		(gfs1 && di->__pad1 == GFS_FILE_DIR);
@@ -269,9 +269,12 @@ void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 			p = be64_to_cpu(*(uint64_t *)(buf + x));
 			if (p) {
 				indirect->ii[indirect_blocks].block = p;
+				indirect->ii[indirect_blocks].mp.mp_list[0] =
+					ptroff;
 				indirect->ii[indirect_blocks].is_dir = FALSE;
 				indirect_blocks++;
 			}
+			ptroff++;
 		}
 	}
 	else if (isdir && !(di->di_flags & GFS2_DIF_EXHASH)) {
@@ -345,14 +348,20 @@ void do_dinode_extended(struct gfs2_dinode *di, char *buf)
 **
 *******************************************************************************
 ******************************************************************************/
-int do_indirect_extended(char *buf, struct iinfo *iinf)
+int do_indirect_extended(char *buf, struct iinfo *iinf, int hgt)
 {
 	unsigned int x, y;
 	uint64_t p;
 	int i_blocks;
 
 	i_blocks = 0;
-	memset(iinf, 0, sizeof(struct iinfo));
+	for (x = 0; x < 512; x++) {
+		iinf->ii[x].is_dir = 0;
+		iinf->ii[x].height = 0;
+		iinf->ii[x].block = 0;
+		iinf->ii[x].dirents = 0;
+		memset(&iinf->ii[x].dirent, 0, sizeof(struct gfs2_dirents));
+	}
 	for (x = (gfs1 ? sizeof(struct gfs_indirect):
 			  sizeof(struct gfs2_meta_header)), y = 0;
 		 x < sbd.bsize;
@@ -360,6 +369,7 @@ int do_indirect_extended(char *buf, struct iinfo *iinf)
 		p = be64_to_cpu(*(uint64_t *)(buf + x));
 		if (p) {
 			iinf->ii[i_blocks].block = p;
+			iinf->ii[i_blocks].mp.mp_list[hgt] = i_blocks;
 			iinf->ii[i_blocks].is_dir = FALSE;
 			i_blocks++;
 		}
diff --git a/gfs2/edit/gfs2hex.h b/gfs2/edit/gfs2hex.h
index eb1ead4..68b98ea 100644
--- a/gfs2/edit/gfs2hex.h
+++ b/gfs2/edit/gfs2hex.h
@@ -14,10 +14,14 @@
 #ifndef __GFS2HEX_DOT_H__
 #define __GFS2HEX_DOT_H__
 
+#include "hexedit.h"
 
 int display_gfs2(void);
 int edit_gfs2(void);
 void do_dinode_extended(struct gfs2_dinode *di, char *buf);
 void print_gfs2(const char *fmt, ...);
+int do_indirect_extended(char *buf, struct iinfo *iinf, int hgt);
+void do_leaf_extended(char *dlebuf, struct iinfo *indir);
+void eol(int col);
 
 #endif /*  __GFS2HEX_DOT_H__  */
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 173f398..0d3af3e 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -49,9 +49,6 @@ const char *allocdesc[2][5] = {
 	{"Free ", "Data ", "FreeM", "Meta ", "Resrv"},};
 
 int display(int identify_only);
-extern void eol(int col);
-extern void do_leaf_extended(char *buf, struct iinfo *indir);
-extern int do_indirect_extended(char *buf, struct iinfo *ii);
 extern void savemeta(const char *out_fn, int slow);
 extern void restoremeta(const char *in_fn, const char *out_device,
 			int printblocksonly);
@@ -1309,14 +1306,70 @@ int display_leaf(struct iinfo *ind)
 }
 
 /* ------------------------------------------------------------------------ */
+/* metapath_to_lblock - convert from metapath, height to logical block      */
+/* ------------------------------------------------------------------------ */
+uint64_t metapath_to_lblock(struct metapath *mp, int hgt)
+{
+	int h;
+	uint64_t lblock = 0;
+	uint64_t factor[GFS2_MAX_META_HEIGHT];
+
+	if (di.di_height < 2)
+		return mp->mp_list[0];
+	/* figure out multiplication factors for each height */
+	memset(&factor, 0, sizeof(factor));
+	factor[di.di_height - 1] = 1ull;
+	for (h = di.di_height - 2; h >= 0; h--)
+		factor[h] = factor[h + 1] * sbd.sd_inptrs;
+	for (h = 0; h <= hgt; h++)
+		lblock += (mp->mp_list[h] * factor[h]);
+	return lblock;
+}
+
+/* ------------------------------------------------------------------------ */
+/* dinode_valid - check if we have a dinode in recent history               */
+/* ------------------------------------------------------------------------ */
+int dinode_valid(void)
+{
+	int i;
+
+	if (gfs2_struct_type == GFS2_METATYPE_DI)
+		return 1;
+	for (i = 0; i <= blockhist && i < 5; i++) {
+		if (blockstack[(blockhist - i) %
+			       BLOCK_STACK_SIZE].gfs2_struct_type ==
+		    GFS2_METATYPE_DI)
+			return 1;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* get_height                                                               */
+/* ------------------------------------------------------------------------ */
+int get_height(void)
+{
+	int cur_height = 0, i;
+
+	if (gfs2_struct_type != GFS2_METATYPE_DI) {
+		for (i = 0; i <= blockhist && i < 5; i++) {
+			if (blockstack[(blockhist - i) %
+				       BLOCK_STACK_SIZE].gfs2_struct_type ==
+			    GFS2_METATYPE_DI)
+				break;
+			cur_height++;
+		}
+	}
+	return cur_height;
+}
+
+/* ------------------------------------------------------------------------ */
 /* display_indirect                                                         */
 /* ------------------------------------------------------------------------ */
 int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff)
 {
 	int start_line, total_dirents;
-	int i, cur_height = -1, pndx;
-	uint64_t factor[5]={0,0,0,0,0};
-	int offsets[5];
+	int cur_height = -1, pndx;
 
 	last_entry_onscreen[dmode] = 0;
 	if (!has_indirect_blocks())
@@ -1335,39 +1388,15 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 				   indblocks);
 	}
 	total_dirents = 0;
-	/* Figure out multiplication factors for indirect pointers. */
-	if (!S_ISDIR(di.di_mode)) {
-		memset(&offsets, 0, sizeof(offsets));
+	if (dinode_valid() && !S_ISDIR(di.di_mode)) {
 		/* See if we are on an inode or have one in history. */
-		cur_height = level;
-		if (!level && gfs2_struct_type != GFS2_METATYPE_DI) {
-			for (i = 0; i <= blockhist && i < 5; i++) {
-				offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode];
-				if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI)
-					break;
-				cur_height++;
-			}
-		}
-		if (cur_height >= 0) {
-			int diptrs, inptrs;
-
-			if (gfs1) {
-				diptrs = 483;
-				inptrs = 501;
-			} else {
-				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.*/
-			/* This is how much data is represented by each      */
-			/* indirect pointer at each height.                  */
-			factor[0] = 1ull;
-			for (i = 0; i < di.di_height; i++)
-				factor[i + 1] = factor[i] * inptrs;
+		if (level)
+			cur_height = level;
+		else {
+			cur_height = get_height();
+			print_gfs2("  (at height %d of %d)",
+				   cur_height, di.di_height);
 		}
-		if (!level)
-			print_gfs2("  (at height %d)", cur_height);
 	}
 	eol(0);
 	if (!level && indblocks) {
@@ -1412,19 +1441,13 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 				COLORS_NORMAL;
 			}
 		}
-		if (!S_ISDIR(di.di_mode)) {
-			int hgt;
-			file_offset = startoff;
+		if (dinode_valid() && !S_ISDIR(di.di_mode)) {
 			float human_off;
 			char h;
 
-			/* Now divide by how deep we are at the moment.      */
-			/* This is how much data is represented by each      */
-			/* indirect pointer for each height we've traversed. */
-			offsets[0] = pndx;
-			for (hgt = cur_height; hgt >= 0; hgt--)
-				file_offset += offsets[cur_height - hgt] *
-					factor[di.di_height - hgt - 1] * sbd.bsize;
+			file_offset = metapath_to_lblock(&ind->ii[pndx].mp,
+							 cur_height) *
+				sbd.bsize;
 			print_gfs2("     ");
 			h = 'K';
 			human_off = (file_offset / 1024.0);
@@ -1439,8 +1462,9 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 		}
 		else
 			file_offset = 0;
-		if (!termlines && ((level + 1 < di.di_height) ||
-				   (S_ISDIR(di.di_mode) && !level))) {
+		if (dinode_valid() && !termlines &&
+		    ((level + 1 < di.di_height) ||
+		     (S_ISDIR(di.di_mode) && !level))) {
 			struct iinfo *more_indir;
 			int more_ind;
 			char *tmpbuf;
@@ -1467,8 +1491,19 @@ int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t start
 					do_leaf_extended(tmpbuf, more_indir);
 					display_leaf(more_indir);
 				} else {
+					int x;
+
+					for (x = 0; x < 512; x++) {
+						memcpy(&more_indir->ii[x].mp,
+						       &ind->ii[pndx].mp,
+						       sizeof(struct metapath));
+						more_indir->ii[x].
+							mp.mp_list[cur_height+1] =
+							x;
+					}
 					more_ind = do_indirect_extended(tmpbuf,
-									more_indir);
+							more_indir,
+							cur_height + 1);
 					display_indirect(more_indir,
 							 more_ind, level + 1,
 							 file_offset);
@@ -1827,8 +1862,15 @@ int display(int identify_only)
 		do_dinode_extended(&di, buf); /* get extended data, if any */
 	}
 	else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
-		do_indirect_extended(buf, indirect);
-		indirect_blocks = 1;
+		int i, hgt = get_height();
+
+		if (blockhist) {
+			for (i = 0; i < 512; i++)
+				memcpy(&indirect->ii[i].mp,
+				       &blockstack[blockhist - 1].mp,
+				       sizeof(struct metapath));
+		}
+		indirect_blocks = do_indirect_extended(buf, indirect, hgt);
 	}
 	else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
 		do_leaf_extended(buf, indirect);
@@ -1877,6 +1919,10 @@ void push_block(uint64_t blk)
 			blockstack[bhst].lines_per_row[i] = lines_per_row[i];
 		}
 		blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
+		if (edit_row[dmode] >= 0)
+			memcpy(&blockstack[bhst].mp,
+			       &indirect->ii[edit_row[dmode]].mp,
+			       sizeof(struct metapath));
 		blockhist++;
 		blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
 	}
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 95cdca9..d7dbe85 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -193,8 +193,10 @@ struct gfs2_dirents {
 
 struct indirect_info {
 	int is_dir;
+	int height;
 	uint64_t block;
 	uint32_t dirents;
+	struct metapath mp;
 	struct gfs2_dirents dirent[64];
 };
 
@@ -211,6 +213,7 @@ struct blkstack_info {
 	int edit_col[DMODES];
 	enum dsp_mode dmode;
 	int gfs2_struct_type;
+	struct metapath mp;
 };
 
 struct gfs_sb {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]