LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File gfs2_edit_better_printing_of_dir_leaf_information.patch of Package cluster (Project home:sschapiro:openstack:upstream)

commit e2407a7f1994799c14984374af2e8e6dce489654
Author: Bob Peterson <bob@ganesha.(none)>
Date:   Thu Sep 30 11:17:18 2010 -0500

    gfs2_edit: better printing of directory leaf information
    
    This patch gives gfs2_edit the ability to better parse out and print
    directory information for exhash directories several levels deep.
    
    rhbz#634623

diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index 00c4481..15c3fa5 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -411,17 +411,25 @@ int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt)
 **
 ** Output(s):
 **
-** Returns:
+** Returns: next leaf block, if any, in a chain of leaf blocks
 **
 *******************************************************************************
 ******************************************************************************/
-void do_leaf_extended(char *dlebuf, struct iinfo *indir)
+uint64_t do_leaf_extended(char *dlebuf, struct iinfo *indir)
 {
 	int x, i;
 	struct gfs2_dirent de;
+	struct gfs2_leaf leaf;
+	struct gfs2_buffer_head tbh; /* kludge */
 
 	x = 0;
 	memset(indir, 0, sizeof(*indir));
+	tbh.b_data = dlebuf;
+	gfs2_leaf_in(&leaf, &tbh);
+	indir->ii[0].lf_depth = leaf.lf_depth;
+	indir->ii[0].lf_entries = leaf.lf_entries;
+	indir->ii[0].lf_dirent_format = leaf.lf_dirent_format;
+	indir->ii[0].lf_next = leaf.lf_next;
 	/* Directory Entries: */
 	for (i = sizeof(struct gfs2_leaf); i < sbd.bsize;
 	     i += de.de_rec_len) {
@@ -442,6 +450,7 @@ void do_leaf_extended(char *dlebuf, struct iinfo *indir)
 		if (de.de_rec_len <= sizeof(struct gfs2_dirent))
 			break;
 	}
+	return leaf.lf_next;
 }
 
 
diff --git a/gfs2/edit/gfs2hex.h b/gfs2/edit/gfs2hex.h
index d18dd59..3c55be4 100644
--- a/gfs2/edit/gfs2hex.h
+++ b/gfs2/edit/gfs2hex.h
@@ -8,7 +8,7 @@ int edit_gfs2(void);
 void do_dinode_extended(struct gfs2_dinode *di, struct gfs2_buffer_head *lbh);
 void print_gfs2(const char *fmt, ...);
 int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt);
-void do_leaf_extended(char *dlebuf, struct iinfo *indir);
+uint64_t 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 408b763..1f7cc14 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -75,6 +75,9 @@ int display(int identify_only);
 		}						\
 	} while(0)
 
+static int display_indirect(struct iinfo *ind, int indblocks, int level,
+			    uint64_t startoff);
+
 static int gfs2_dinode_printval(struct gfs2_dinode *dip, const char *strfield)
 {
 	checkprint(strfield, dip, di_mode);
@@ -1247,7 +1250,11 @@ static int display_leaf(struct iinfo *ind)
 	if (gfs2_struct_type == GFS2_METATYPE_SB)
 		print_gfs2("The superblock has 2 directories");
 	else
-		print_gfs2("This directory block contains %d directory entries.",
+		print_gfs2("Directory block: lf_depth:%d, lf_entries:%d,"
+			   "fmt:%d next=0x%llx (%d dirents).",
+			   ind->ii[0].lf_depth, ind->ii[0].lf_entries,
+			   ind->ii[0].lf_dirent_format,
+			   ind->ii[0].lf_next,
 			   ind->ii[0].dirents);
 
 	start_line = line;
@@ -1256,7 +1263,7 @@ static int display_leaf(struct iinfo *ind)
 		    + start_row[dmode])
 			break;
 		total_dirents++;
-		if (ind->ii[0].dirents > 1) {
+		if (ind->ii[0].dirents >= 1) {
 			eol(5);
 			if (termlines) {
 				if (edit_row[dmode] >=0 &&
@@ -1350,9 +1357,76 @@ static int get_height(void)
 }
 
 /* ------------------------------------------------------------------------ */
+/* print_block_details                                                      */
+/* ------------------------------------------------------------------------ */
+static void print_block_details(struct iinfo *ind, int level, int cur_height,
+				int pndx, uint64_t file_offset)
+{
+	struct iinfo *more_indir;
+	int more_ind;
+	char *tmpbuf;
+	uint64_t thisblk;
+
+	thisblk = ind->ii[pndx].block;
+	more_indir = malloc(sizeof(struct iinfo));
+	if (!more_indir) {
+		fprintf(stderr, "Out of memory in function "
+			"display_indirect\n");
+		return;
+	}
+	tmpbuf = malloc(sbd.bsize);
+	if (!tmpbuf) {
+		fprintf(stderr, "Out of memory in function "
+			"display_indirect\n");
+		return;
+	}
+	while (thisblk) {
+		lseek(sbd.device_fd, thisblk * sbd.bsize, SEEK_SET);
+		/* read in the desired block */
+		if (read(sbd.device_fd, tmpbuf, sbd.bsize) != sbd.bsize) {
+			fprintf(stderr, "bad read: %s from %s:%d: block %lld "
+				"(0x%llx)\n", strerror(errno), __FUNCTION__,
+				__LINE__,
+				(unsigned long long)ind->ii[pndx].block,
+				(unsigned long long)ind->ii[pndx].block);
+			exit(-1);
+		}
+		thisblk = 0;
+		memset(more_indir, 0, sizeof(struct iinfo));
+		if (S_ISDIR(di.di_mode) && level == di.di_height) {
+			thisblk = 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,
+							cur_height + 1);
+			display_indirect(more_indir, more_ind, level + 1,
+					 file_offset);
+		}
+		if (thisblk) {
+			eol(0);
+			if (termlines)
+				move(line,9);
+			print_gfs2("Continuation block 0x%llx / %lld",
+				   thisblk, thisblk);
+		}
+	}
+	free(tmpbuf);
+	free(more_indir);
+}
+
+/* ------------------------------------------------------------------------ */
 /* display_indirect                                                         */
 /* ------------------------------------------------------------------------ */
-static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff)
+static int display_indirect(struct iinfo *ind, int indblocks, int level,
+			    uint64_t startoff)
 {
 	int start_line, total_dirents;
 	int cur_height = -1, pndx;
@@ -1368,8 +1442,7 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 			else
 				print_gfs2("This inode contains %d indirect blocks",
 					   indblocks);
-		}
-		else
+		} else
 			print_gfs2("This indirect block contains %d indirect blocks",
 				   indblocks);
 	}
@@ -1397,6 +1470,8 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 		 pndx++) {
 		uint64_t file_offset;
 
+		if (pndx && ind->ii[pndx].block == ind->ii[pndx - 1].block)
+			continue;
 		print_entry_ndx = pndx;
 		if (termlines) {
 			if (edit_row[dmode] >= 0 &&
@@ -1450,53 +1525,9 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_
 			file_offset = 0;
 		if (dinode_valid() && !termlines &&
 		    ((level + 1 < di.di_height) ||
-		     (S_ISDIR(di.di_mode) && !level))) {
-			struct iinfo *more_indir;
-			int more_ind;
-			char *tmpbuf;
-			
-			more_indir = malloc(sizeof(struct iinfo));
-			tmpbuf = malloc(sbd.bsize);
-			if (tmpbuf) {
-				lseek(sbd.device_fd,
-				      ind->ii[pndx].block * sbd.bsize,
-				      SEEK_SET);
-				/* read in the desired block */
-				if (read(sbd.device_fd, tmpbuf, sbd.bsize) !=
-				    sbd.bsize) {
-					fprintf(stderr, "bad read: %s from %s:"
-						"%d: block %lld (0x%llx)\n",
-						strerror(errno),
-						__FUNCTION__, __LINE__,
-						(unsigned long long)ind->ii[pndx].block,
-						(unsigned long long)ind->ii[pndx].block);
-					exit(-1);
-				}
-				memset(more_indir, 0, sizeof(struct iinfo));
-				if (S_ISDIR(di.di_mode)) {
-					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,
-							cur_height + 1);
-					display_indirect(more_indir,
-							 more_ind, level + 1,
-							 file_offset);
-				}
-				free(tmpbuf);
-			}
-			free(more_indir);
+		     (S_ISDIR(di.di_mode) && level <= di.di_height))) {
+			print_block_details(ind, level, cur_height, pndx,
+					    file_offset);
 		}
 		print_entry_ndx = pndx; /* restore after recursion */
 		eol(0);
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 549c3af..944e8cc 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -178,6 +178,10 @@ struct indirect_info {
 	int height;
 	uint64_t block;
 	uint32_t dirents;
+	uint16_t lf_depth;
+	uint16_t lf_entries;
+	uint32_t lf_dirent_format;
+	uint64_t lf_next;
 	struct metapath mp;
 	struct gfs2_dirents dirent[64];
 };