public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
From: Bob Peterson <rpeterso@fedoraproject.org>
To: cluster-cvs-relay@redhat.com
Subject: cluster: STABLE2 - gfs2_edit -p block# shows wrong height/offset on gfs1 and segfaults on gfs2
Date: Wed, 02 Sep 2009 16:04:00 -0000	[thread overview]
Message-ID: <20090902160354.81A3F120209@lists.fedorahosted.org> (raw)

Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9193f209caf578558b64b3451dec0954e710a851
Commit:        9193f209caf578558b64b3451dec0954e710a851
Parent:        b4d4b6137c13f5fb4e267cffbb97e0e885fef617
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 11:05:17 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 010fda5..1b9071f 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -242,7 +242,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);
@@ -256,9 +256,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)) {
@@ -332,14 +335,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;
@@ -347,6 +356,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 4dd92d4..9a1df21 100644
--- a/gfs2/edit/gfs2hex.h
+++ b/gfs2/edit/gfs2hex.h
@@ -1,10 +1,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 8f34d67..1027982 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -34,9 +34,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(char *out_fn, int slow);
 extern void restoremeta(const char *in_fn, const char *out_device,
 			int printblocksonly);
@@ -1294,14 +1291,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())
@@ -1320,39 +1373,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) {
@@ -1397,19 +1426,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);
@@ -1424,8 +1447,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;
@@ -1452,8 +1476,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);
@@ -1812,8 +1847,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);
@@ -1862,6 +1904,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 9d1fdc8..ecf6f3a 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -181,8 +181,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];
 };
 
@@ -199,6 +201,7 @@ struct blkstack_info {
 	int edit_col[DMODES];
 	enum dsp_mode dmode;
 	int gfs2_struct_type;
+	struct metapath mp;
 };
 
 struct gfs_sb {


                 reply	other threads:[~2009-09-02 16:04 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090902160354.81A3F120209@lists.fedorahosted.org \
    --to=rpeterso@fedoraproject.org \
    --cc=cluster-cvs-relay@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).