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: STABLE3 - 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=03a04c47891c30dea49a8aaa3c7ed596d9048022
Commit:        03a04c47891c30dea49a8aaa3c7ed596d9048022
Parent:        81ada023e8280a0199dd5e646fd475c6ed0f56e0
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Wed Sep 2 10:13:14 2009 -0500
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Wed Sep 2 10:13:14 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 |    2 +-
 gfs2/edit/hexedit.c |  151 +++++++++++++++++++++++++++++++++------------------
 gfs2/edit/hexedit.h |    3 +
 4 files changed, 115 insertions(+), 57 deletions(-)

diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index b7e9c81..a4ec02c 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -278,7 +278,7 @@ static int indirect_dirent(struct indirect_info *indir, char *ptr, int d)
 ******************************************************************************/
 void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf)
 {
-	unsigned int x, y;
+	unsigned int x, y, ptroff = 0;
 	uint64_t p, last;
 	int isdir = !!(S_ISDIR(dine->di_mode)) || 
 		(gfs1 && dine->__pad1 == GFS_FILE_DIR);
@@ -292,9 +292,12 @@ void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf)
 			p = be64_to_cpu(*(uint64_t *)(dinebuf + 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 && !(dine->di_flags & GFS2_DIF_EXHASH)) {
@@ -368,14 +371,20 @@ void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf)
 **
 *******************************************************************************
 ******************************************************************************/
-int do_indirect_extended(char *diebuf, struct iinfo *iinf)
+int do_indirect_extended(char *diebuf, 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;
@@ -383,6 +392,7 @@ int do_indirect_extended(char *diebuf, struct iinfo *iinf)
 		p = be64_to_cpu(*(uint64_t *)(diebuf + 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 93ed134..5a351d6 100644
--- a/gfs2/edit/gfs2hex.h
+++ b/gfs2/edit/gfs2hex.h
@@ -7,7 +7,7 @@ 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 *diebuf, struct iinfo *iinf);
+int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt);
 void do_leaf_extended(char *dlebuf, struct iinfo *indir);
 void eol(int col);
 
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 03ca673..8ba3d03 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -38,7 +38,6 @@ const char *allocdesc[2][5] = {
 
 int display(int identify_only);
 extern void do_leaf_extended(char *buf, struct iinfo *indir);
-extern int do_indirect_extended(char *buf, struct iinfo *ii);
 extern void savemeta(char *out_fn, int slow);
 extern void restoremeta(const char *in_fn, const char *out_device,
 			int printblocksonly);
@@ -427,8 +426,6 @@ static void print_usage(void)
 	Erase();
 }
 
-
-
 /* ------------------------------------------------------------------------ */
 /* get_block_type                                                           */
 /* returns: metatype if block is a GFS2 structure block type                */
@@ -1298,14 +1295,70 @@ static int display_leaf(struct iinfo *ind)
 }
 
 /* ------------------------------------------------------------------------ */
+/* metapath_to_lblock - convert from metapath, height to logical block      */
+/* ------------------------------------------------------------------------ */
+static 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               */
+/* ------------------------------------------------------------------------ */
+static 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                                                               */
+/* ------------------------------------------------------------------------ */
+static 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                                                         */
 /* ------------------------------------------------------------------------ */
 static 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())
@@ -1324,39 +1377,15 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 				   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) {
@@ -1401,20 +1430,13 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 				COLORS_NORMAL;
 			}
 		}
-		if (!S_ISDIR(di.di_mode)) {
-			int hgt;
+		if (dinode_valid() && !S_ISDIR(di.di_mode)) {
 			float human_off;
 			char h;
 
-			file_offset = startoff;
-
-			/* 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);
@@ -1429,8 +1451,9 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 		}
 		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;
@@ -1457,8 +1480,19 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 					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);
@@ -1824,8 +1858,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);
@@ -1874,6 +1915,10 @@ static 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 e53f72f..e4b0ea1 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -171,8 +171,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];
 };
 
@@ -189,6 +191,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]