gfs2-utils: master - gfs2_edit: Separate out the journal-related functions to journal.c

Andrew Price andyp at fedoraproject.org
Mon Mar 3 18:45:00 UTC 2014


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=478f093f301149c54db72a94ff7e9148ac00444e
Commit:        478f093f301149c54db72a94ff7e9148ac00444e
Parent:        57f0e1b70dbd1de7aca9b2bdc09d49d28c25d888
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Thu Feb 27 09:23:04 2014 -0500
Committer:     Andrew Price <anprice at redhat.com>
CommitterDate: Thu Feb 27 20:27:07 2014 +0000

gfs2_edit: Separate out the journal-related functions to journal.c

This patch takes all the code related to dumping journals and puts them
all in a separate journal.c. This will later be used for journal parsing.

Signed-off-by: Bob Peterson <rpeterso at redhat.com>
---
 gfs2/edit/Makefile.am |    4 +-
 gfs2/edit/hexedit.c   |  323 +---------------------------------------------
 gfs2/edit/hexedit.h   |    2 +
 gfs2/edit/journal.c   |  349 +++++++++++++++++++++++++++++++++++++++++++++++++
 gfs2/edit/journal.h   |    8 +
 5 files changed, 363 insertions(+), 323 deletions(-)

diff --git a/gfs2/edit/Makefile.am b/gfs2/edit/Makefile.am
index c4814dc..8b977ae 100644
--- a/gfs2/edit/Makefile.am
+++ b/gfs2/edit/Makefile.am
@@ -2,9 +2,9 @@ MAINTAINERCLEANFILES	= Makefile.in
 
 sbin_PROGRAMS		= gfs2_edit
 
-noinst_HEADERS		= gfs2hex.h hexedit.h extended.h
+noinst_HEADERS		= gfs2hex.h hexedit.h extended.h journal.h
 
-gfs2_edit_SOURCES	= gfs2hex.c hexedit.c savemeta.c extended.c
+gfs2_edit_SOURCES	= gfs2hex.c hexedit.c savemeta.c extended.c journal.c
 
 gfs2_edit_CPPFLAGS	= -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM \
 			  -I$(top_srcdir)/gfs2/include \
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index cf57ec8..18d06c7 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -26,6 +26,7 @@
 #include "libgfs2.h"
 #include "gfs2hex.h"
 #include "extended.h"
+#include "journal.h"
 
 const char *mtypes[] = {"none", "sb", "rg", "rb", "di", "in", "lf", "jd",
 			"lh", "ld", "ea", "ed", "lb", "13", "qc"};
@@ -577,7 +578,7 @@ static void print_usage(void)
 /* returns: metatype if block is a GFS2 structure block type                */
 /*          0 if block is not a GFS2 structure                              */
 /* ------------------------------------------------------------------------ */
-static uint32_t get_block_type(const struct gfs2_buffer_head *lbh)
+uint32_t get_block_type(const struct gfs2_buffer_head *lbh)
 {
 	const struct gfs2_meta_header *mh = lbh->iov.iov_base;
 
@@ -1508,61 +1509,6 @@ static uint64_t pop_block(void)
 }
 
 /* ------------------------------------------------------------------------ */
-/* find_journal_block - figure out where a journal starts, given the name   */
-/* Returns: journal block number, changes j_size to the journal size        */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_journal_block(const char *journal, uint64_t *j_size)
-{
-	int journal_num;
-	uint64_t jindex_block, jblock = 0;
-	int amtread;
-	struct gfs2_buffer_head *jindex_bh, *j_bh;
-	char jbuf[sbd.bsize];
-
-	journal_num = atoi(journal + 7);
-	/* Figure out the block of the jindex file */
-	if (sbd.gfs1)
-		jindex_block = sbd1->sb_jindex_di.no_addr;
-	else
-		jindex_block = masterblock("jindex");
-	/* read in the block */
-	jindex_bh = bread(&sbd, jindex_block);
-	/* get the dinode data from it. */
-	gfs2_dinode_in(&di, jindex_bh); /* parse disk inode to struct*/
-
-	if (!sbd.gfs1)
-		do_dinode_extended(&di, jindex_bh); /* parse dir. */
-
-	if (sbd.gfs1) {
-		struct gfs2_inode *jiinode;
-		struct gfs_jindex ji;
-
-		jiinode = lgfs2_inode_get(&sbd, jindex_bh);
-		if (jiinode == NULL)
-			return 0;
-		amtread = gfs2_readi(jiinode, (void *)&jbuf,
-				   journal_num * sizeof(struct gfs_jindex),
-				   sizeof(struct gfs_jindex));
-		if (amtread) {
-			gfs_jindex_in(&ji, jbuf);
-			jblock = ji.ji_addr;
-			*j_size = ji.ji_nsegment * 0x10;
-		}
-		inode_put(&jiinode);
-	} else {
-		struct gfs2_dinode jdi;
-
-		jblock = indirect->ii[0].dirent[journal_num + 2].block;
-		j_bh = bread(&sbd, jblock);
-		gfs2_dinode_in(&jdi, j_bh);/* parse dinode to struct */
-		*j_size = jdi.di_size;
-		brelse(j_bh);
-	}
-	brelse(jindex_bh);
-	return jblock;
-}
-
-/* ------------------------------------------------------------------------ */
 /* Find next metadata block of a given type AFTER a given point in the fs   */
 /*                                                                          */
 /* This is used to find blocks that aren't represented in the bitmaps, such */
@@ -2577,271 +2523,6 @@ void gfs_log_header_print(struct gfs_log_header *lh)
 }
 
 /* ------------------------------------------------------------------------ */
-/* print_ld_blocks - print all blocks given in a log descriptor             */
-/* returns: the number of block numbers it printed                          */
-/* ------------------------------------------------------------------------ */
-static int print_ld_blocks(const uint64_t *b, const char *end, int start_line)
-{
-	int bcount = 0, i = 0;
-	static char str[256];
-
-	while (*b && (char *)b < end) {
-		if (!termlines ||
-		    (print_entry_ndx >= start_row[dmode] &&
-		     ((print_entry_ndx - start_row[dmode])+1) *
-		     lines_per_row[dmode] <= termlines - start_line - 2)) {
-			if (i && i % 4 == 0) {
-				eol(0);
-				print_gfs2("                    ");
-			}
-			i++;
-			sprintf(str, "0x%llx",
-				(unsigned long long)be64_to_cpu(*b));
-			print_gfs2("%-18.18s ", str);
-			bcount++;
-		}
-		b++;
-		if (sbd.gfs1)
-			b++;
-	}
-	eol(0);
-	return bcount;
-}
-
-/* ------------------------------------------------------------------------ */
-/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block #     */
-/*              of the first bit of data read.                              */
-/* ------------------------------------------------------------------------ */
-static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
-	       unsigned int size, uint64_t *abs_block)
-{
-	struct gfs2_sbd *sdp = ip->i_sbd;
-	struct gfs2_buffer_head *lbh;
-	uint64_t lblock, dblock;
-	unsigned int o;
-	uint32_t extlen = 0;
-	unsigned int amount;
-	int not_new = 0;
-	int isdir = !!(S_ISDIR(ip->i_di.di_mode));
-	int copied = 0;
-
-	*abs_block = 0;
-	if (roffset >= ip->i_di.di_size)
-		return 0;
-	if ((roffset + size) > ip->i_di.di_size)
-		size = ip->i_di.di_size - roffset;
-	if (!size)
-		return 0;
-	if (isdir) {
-		o = roffset % sdp->sd_jbsize;
-		lblock = roffset / sdp->sd_jbsize;
-	} else {
-		lblock = roffset >> sdp->sd_sb.sb_bsize_shift;
-		o = roffset & (sdp->bsize - 1);
-	}
-
-	if (!ip->i_di.di_height) /* inode_is_stuffed */
-		o += sizeof(struct gfs2_dinode);
-	else if (isdir)
-		o += sizeof(struct gfs2_meta_header);
-
-	while (copied < size) {
-		amount = size - copied;
-		if (amount > sdp->bsize - o)
-			amount = sdp->bsize - o;
-		if (!extlen)
-			block_map(ip, lblock, &not_new, &dblock, &extlen,
-				  FALSE);
-		if (dblock) {
-			lbh = bread(sdp, dblock);
-			if (*abs_block == 0)
-				*abs_block = lbh->b_blocknr;
-			dblock++;
-			extlen--;
-		} else
-			lbh = NULL;
-		if (lbh) {
-			memcpy(rbuf, lbh->b_data + o, amount);
-			brelse(lbh);
-		} else {
-			memset(rbuf, 0, amount);
-		}
-		copied += amount;
-		lblock++;
-		o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
-	}
-	return copied;
-}
-
-static void check_journal_wrap(uint64_t seq, uint64_t *highest_seq)
-{
-	if (seq < *highest_seq) {
-		print_gfs2("------------------------------------------------"
-			   "------------------------------------------------");
-		eol(0);
-		print_gfs2("Journal wrapped here.");
-		eol(0);
-		print_gfs2("------------------------------------------------"
-			   "------------------------------------------------");
-		eol(0);
-	}
-	*highest_seq = seq;
-}
-
-static int is_meta(struct gfs2_buffer_head *lbh)
-{
-	uint32_t check_magic = ((struct gfs2_meta_header *)(lbh->b_data))->mh_magic;
-
-	check_magic = be32_to_cpu(check_magic);
-	if (check_magic == GFS2_MAGIC)
-		return 1;
-	return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* dump_journal - dump a journal file's contents.                           */
-/* ------------------------------------------------------------------------ */
-static void dump_journal(const char *journal)
-{
-	struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
-	uint64_t jblock, j_size, jb, abs_block, saveblk;
-	int error, start_line, journal_num;
-	struct gfs2_inode *j_inode = NULL;
-	int ld_blocks = 0;
-	uint64_t highest_seq = 0;
-	char *jbuf = NULL;
-
-	start_line = line;
-	lines_per_row[dmode] = 1;
-	error = 0;
-	journal_num = atoi(journal + 7);
-	print_gfs2("Dumping journal #%d.", journal_num);
-	eol(0);
-	jblock = find_journal_block(journal, &j_size);
-	if (!jblock)
-		return;
-	if (!sbd.gfs1) {
-		j_bh = bread(&sbd, jblock);
-		j_inode = lgfs2_inode_get(&sbd, j_bh);
-		if (j_inode == NULL) {
-			fprintf(stderr, "Out of memory\n");
-			exit(-1);
-		}
-		jbuf = malloc(sbd.bsize);
-		if (jbuf == NULL) {
-			fprintf(stderr, "Out of memory\n");
-			exit(-1);
-		}
-	}
-
-	for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1:sbd.bsize)) {
-		if (sbd.gfs1) {
-			if (j_bh)
-				brelse(j_bh);
-			j_bh = bread(&sbd, jblock + jb);
-			abs_block = jblock + jb;
-			dummy_bh.b_data = j_bh->b_data;
-		} else {
-			error = fsck_readi(j_inode, (void *)jbuf, jb,
-					   sbd.bsize, &abs_block);
-			if (!error) /* end of file */
-				break;
-			dummy_bh.b_data = jbuf;
-		}
-		if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
-			uint64_t *b;
-			struct gfs2_log_descriptor ld;
-			int ltndx;
-			uint32_t logtypes[2][6] = {
-				{GFS2_LOG_DESC_METADATA,
-				 GFS2_LOG_DESC_REVOKE,
-				 GFS2_LOG_DESC_JDATA,
-				 0, 0, 0},
-				{GFS_LOG_DESC_METADATA,
-				 GFS_LOG_DESC_IUL,
-				 GFS_LOG_DESC_IDA,
-				 GFS_LOG_DESC_Q,
-				 GFS_LOG_DESC_LAST,
-				 0}};
-			const char *logtypestr[2][6] = {
-				{"Metadata", "Revoke", "Jdata",
-				 "Unknown", "Unknown", "Unknown"},
-				{"Metadata", "Unlinked inode", "Dealloc inode",
-				 "Quota", "Final Entry", "Unknown"}};
-
-			print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
-				   abs_block, jb / (sbd.gfs1 ? 1 : sbd.bsize));
-			gfs2_log_descriptor_in(&ld, &dummy_bh);
-			print_gfs2("type %d ", ld.ld_type);
-
-			for (ltndx = 0;; ltndx++) {
-				if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
-				    logtypes[sbd.gfs1][ltndx] == 0)
-					break;
-			}
-			print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
-			print_gfs2("len:%u, data1: %u",
-				   ld.ld_length, ld.ld_data1);
-			eol(0);
-			print_gfs2("                    ");
-			if (sbd.gfs1)
-				b = (uint64_t *)(dummy_bh.b_data +
-					sizeof(struct gfs_log_descriptor));
-			else
-				b = (uint64_t *)(dummy_bh.b_data +
-					sizeof(struct gfs2_log_descriptor));
-			ld_blocks = ld.ld_data1;
-			ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
-							 sbd.bsize),
-						     start_line);
-		} else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
-			struct gfs2_log_header lh;
-			struct gfs_log_header lh1;
-
-			if (sbd.gfs1) {
-				gfs_log_header_in(&lh1, &dummy_bh);
-				check_journal_wrap(lh1.lh_sequence,
-						   &highest_seq);
-				print_gfs2("0x%llx (j+%4llx): Log header: "
-					   "Flags:%x, Seq: 0x%x, "
-					   "1st: 0x%x, tail: 0x%x, "
-					   "last: 0x%x", abs_block,
-					   jb, lh1.lh_flags, lh1.lh_sequence,
-					   lh1.lh_first, lh1.lh_tail,
-					   lh1.lh_last_dump);
-			} else {
-				gfs2_log_header_in(&lh, &dummy_bh);
-				check_journal_wrap(lh.lh_sequence,
-						   &highest_seq);
-				print_gfs2("0x%llx (j+%4llx): Log header: Seq"
-					   ": 0x%x, tail: 0x%x, blk: 0x%x",
-					   abs_block,
-					   jb / sbd.bsize, lh.lh_sequence,
-					   lh.lh_tail, lh.lh_blkno);
-			}
-			eol(0);
-		} else if (sbd.gfs1 && ld_blocks > 0) {
-			print_gfs2("0x%llx (j+%4llx): GFS log descriptor"
-				   " continuation block", abs_block, jb);
-			eol(0);
-			print_gfs2("                    ");
-			ld_blocks -= print_ld_blocks((uint64_t *)dummy_bh.b_data,
-						     (dummy_bh.b_data +
-						      sbd.bsize), start_line);
-		} else if (details && is_meta(&dummy_bh)) {
-			saveblk = block;
-			block = abs_block;
-			display(0);
-			block = saveblk;
-		}
-	}
-	inode_put(&j_inode);
-	brelse(j_bh);
-	blockhist = -1; /* So we don't print anything else */
-	free(jbuf);
-}
-
-/* ------------------------------------------------------------------------ */
 /* usage - print command line usage                                         */
 /* ------------------------------------------------------------------------ */
 static void usage(void)
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 7615242..53a0c72 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -67,6 +67,7 @@ extern const char *block_type_str[15];
 extern int dsplines;
 extern int dsp_lines[DMODES];
 extern int combined_display;
+extern int details;
 
 struct gfs2_dirents {
 	uint64_t block;
@@ -236,5 +237,6 @@ extern uint64_t check_keywords(const char *kword);
 extern uint64_t masterblock(const char *fn);
 extern void gfs_rgrp_print(struct gfs_rgrp *rg);
 extern int has_indirect_blocks(void);
+extern uint32_t get_block_type(const struct gfs2_buffer_head *lbh);
 
 #endif /* __HEXVIEW_DOT_H__ */
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
new file mode 100644
index 0000000..102b4b9
--- /dev/null
+++ b/gfs2/edit/journal.c
@@ -0,0 +1,349 @@
+#include "clusterautoconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <curses.h>
+#include <term.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <dirent.h>
+
+#include <linux/gfs2_ondisk.h>
+#include "copyright.cf"
+
+#include "hexedit.h"
+#include "libgfs2.h"
+#include "extended.h"
+#include "gfs2hex.h"
+#include "journal.h"
+
+/* ------------------------------------------------------------------------ */
+/* find_journal_block - figure out where a journal starts, given the name   */
+/* Returns: journal block number, changes j_size to the journal size        */
+/* ------------------------------------------------------------------------ */
+uint64_t find_journal_block(const char *journal, uint64_t *j_size)
+{
+	int journal_num;
+	uint64_t jindex_block, jblock = 0;
+	int amtread;
+	struct gfs2_buffer_head *jindex_bh, *j_bh;
+	char jbuf[sbd.bsize];
+
+	journal_num = atoi(journal + 7);
+	/* Figure out the block of the jindex file */
+	if (sbd.gfs1)
+		jindex_block = sbd1->sb_jindex_di.no_addr;
+	else
+		jindex_block = masterblock("jindex");
+	/* read in the block */
+	jindex_bh = bread(&sbd, jindex_block);
+	/* get the dinode data from it. */
+	gfs2_dinode_in(&di, jindex_bh); /* parse disk inode to struct*/
+
+	if (!sbd.gfs1)
+		do_dinode_extended(&di, jindex_bh); /* parse dir. */
+
+	if (sbd.gfs1) {
+		struct gfs2_inode *jiinode;
+		struct gfs_jindex ji;
+
+		jiinode = lgfs2_inode_get(&sbd, jindex_bh);
+		if (jiinode == NULL)
+			return 0;
+		amtread = gfs2_readi(jiinode, (void *)&jbuf,
+				   journal_num * sizeof(struct gfs_jindex),
+				   sizeof(struct gfs_jindex));
+		if (amtread) {
+			gfs_jindex_in(&ji, jbuf);
+			jblock = ji.ji_addr;
+			*j_size = ji.ji_nsegment * 0x10;
+		}
+		inode_put(&jiinode);
+	} else {
+		struct gfs2_dinode jdi;
+
+		jblock = indirect->ii[0].dirent[journal_num + 2].block;
+		j_bh = bread(&sbd, jblock);
+		gfs2_dinode_in(&jdi, j_bh);/* parse dinode to struct */
+		*j_size = jdi.di_size;
+		brelse(j_bh);
+	}
+	brelse(jindex_bh);
+	return jblock;
+}
+
+static void check_journal_wrap(uint64_t seq, uint64_t *highest_seq)
+{
+	if (seq < *highest_seq) {
+		print_gfs2("------------------------------------------------"
+			   "------------------------------------------------");
+		eol(0);
+		print_gfs2("Journal wrapped here.");
+		eol(0);
+		print_gfs2("------------------------------------------------"
+			   "------------------------------------------------");
+		eol(0);
+	}
+	*highest_seq = seq;
+}
+
+static int is_meta(struct gfs2_buffer_head *lbh)
+{
+	uint32_t check_magic = ((struct gfs2_meta_header *)(lbh->b_data))->mh_magic;
+
+	check_magic = be32_to_cpu(check_magic);
+	if (check_magic == GFS2_MAGIC)
+		return 1;
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block #     */
+/*              of the first bit of data read.                              */
+/* ------------------------------------------------------------------------ */
+static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
+	       unsigned int size, uint64_t *abs_block)
+{
+	struct gfs2_sbd *sdp = ip->i_sbd;
+	struct gfs2_buffer_head *lbh;
+	uint64_t lblock, dblock;
+	unsigned int o;
+	uint32_t extlen = 0;
+	unsigned int amount;
+	int not_new = 0;
+	int isdir = !!(S_ISDIR(ip->i_di.di_mode));
+	int copied = 0;
+
+	*abs_block = 0;
+	if (roffset >= ip->i_di.di_size)
+		return 0;
+	if ((roffset + size) > ip->i_di.di_size)
+		size = ip->i_di.di_size - roffset;
+	if (!size)
+		return 0;
+	if (isdir) {
+		o = roffset % sdp->sd_jbsize;
+		lblock = roffset / sdp->sd_jbsize;
+	} else {
+		lblock = roffset >> sdp->sd_sb.sb_bsize_shift;
+		o = roffset & (sdp->bsize - 1);
+	}
+
+	if (!ip->i_di.di_height) /* inode_is_stuffed */
+		o += sizeof(struct gfs2_dinode);
+	else if (isdir)
+		o += sizeof(struct gfs2_meta_header);
+
+	while (copied < size) {
+		amount = size - copied;
+		if (amount > sdp->bsize - o)
+			amount = sdp->bsize - o;
+		if (!extlen)
+			block_map(ip, lblock, &not_new, &dblock, &extlen,
+				  FALSE);
+		if (dblock) {
+			lbh = bread(sdp, dblock);
+			if (*abs_block == 0)
+				*abs_block = lbh->b_blocknr;
+			dblock++;
+			extlen--;
+		} else
+			lbh = NULL;
+		if (lbh) {
+			memcpy(rbuf, lbh->b_data + o, amount);
+			brelse(lbh);
+		} else {
+			memset(rbuf, 0, amount);
+		}
+		copied += amount;
+		lblock++;
+		o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
+	}
+	return copied;
+}
+
+/* ------------------------------------------------------------------------ */
+/* print_ld_blocks - print all blocks given in a log descriptor             */
+/* returns: the number of block numbers it printed                          */
+/* ------------------------------------------------------------------------ */
+static int print_ld_blocks(const uint64_t *b, const char *end, int start_line)
+{
+	int bcount = 0, i = 0;
+	static char str[256];
+
+	while (*b && (char *)b < end) {
+		if (!termlines ||
+		    (print_entry_ndx >= start_row[dmode] &&
+		     ((print_entry_ndx - start_row[dmode])+1) *
+		     lines_per_row[dmode] <= termlines - start_line - 2)) {
+			if (i && i % 4 == 0) {
+				eol(0);
+				print_gfs2("                    ");
+			}
+			i++;
+			sprintf(str, "0x%llx",
+				(unsigned long long)be64_to_cpu(*b));
+			print_gfs2("%-18.18s ", str);
+			bcount++;
+		}
+		b++;
+		if (sbd.gfs1)
+			b++;
+	}
+	eol(0);
+	return bcount;
+}
+
+/* ------------------------------------------------------------------------ */
+/* dump_journal - dump a journal file's contents.                           */
+/* ------------------------------------------------------------------------ */
+void dump_journal(const char *journal)
+{
+	struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
+	uint64_t jblock, j_size, jb, abs_block, saveblk;
+	int error, start_line, journal_num;
+	struct gfs2_inode *j_inode = NULL;
+	int ld_blocks = 0;
+	uint64_t highest_seq = 0;
+	char *jbuf = NULL;
+
+	start_line = line;
+	lines_per_row[dmode] = 1;
+	error = 0;
+	journal_num = atoi(journal + 7);
+	print_gfs2("Dumping journal #%d.", journal_num);
+	eol(0);
+	jblock = find_journal_block(journal, &j_size);
+	if (!jblock)
+		return;
+	if (!sbd.gfs1) {
+		j_bh = bread(&sbd, jblock);
+		j_inode = lgfs2_inode_get(&sbd, j_bh);
+		if (j_inode == NULL) {
+			fprintf(stderr, "Out of memory\n");
+			exit(-1);
+		}
+		jbuf = malloc(sbd.bsize);
+		if (jbuf == NULL) {
+			fprintf(stderr, "Out of memory\n");
+			exit(-1);
+		}
+	}
+
+	for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1:sbd.bsize)) {
+		if (sbd.gfs1) {
+			if (j_bh)
+				brelse(j_bh);
+			j_bh = bread(&sbd, jblock + jb);
+			abs_block = jblock + jb;
+			dummy_bh.b_data = j_bh->b_data;
+		} else {
+			error = fsck_readi(j_inode, (void *)jbuf, jb,
+					   sbd.bsize, &abs_block);
+			if (!error) /* end of file */
+				break;
+			dummy_bh.b_data = jbuf;
+		}
+		if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
+			uint64_t *b;
+			struct gfs2_log_descriptor ld;
+			int ltndx;
+			uint32_t logtypes[2][6] = {
+				{GFS2_LOG_DESC_METADATA,
+				 GFS2_LOG_DESC_REVOKE,
+				 GFS2_LOG_DESC_JDATA,
+				 0, 0, 0},
+				{GFS_LOG_DESC_METADATA,
+				 GFS_LOG_DESC_IUL,
+				 GFS_LOG_DESC_IDA,
+				 GFS_LOG_DESC_Q,
+				 GFS_LOG_DESC_LAST,
+				 0}};
+			const char *logtypestr[2][6] = {
+				{"Metadata", "Revoke", "Jdata",
+				 "Unknown", "Unknown", "Unknown"},
+				{"Metadata", "Unlinked inode", "Dealloc inode",
+				 "Quota", "Final Entry", "Unknown"}};
+
+			print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
+				   abs_block, jb / (sbd.gfs1 ? 1 : sbd.bsize));
+			gfs2_log_descriptor_in(&ld, &dummy_bh);
+			print_gfs2("type %d ", ld.ld_type);
+
+			for (ltndx = 0;; ltndx++) {
+				if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
+				    logtypes[sbd.gfs1][ltndx] == 0)
+					break;
+			}
+			print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
+			print_gfs2("len:%u, data1: %u",
+				   ld.ld_length, ld.ld_data1);
+			eol(0);
+			print_gfs2("                    ");
+			if (sbd.gfs1)
+				b = (uint64_t *)(dummy_bh.b_data +
+					sizeof(struct gfs_log_descriptor));
+			else
+				b = (uint64_t *)(dummy_bh.b_data +
+					sizeof(struct gfs2_log_descriptor));
+			ld_blocks = ld.ld_data1;
+			ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
+							 sbd.bsize),
+						     start_line);
+		} else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
+			struct gfs2_log_header lh;
+			struct gfs_log_header lh1;
+
+			if (sbd.gfs1) {
+				gfs_log_header_in(&lh1, &dummy_bh);
+				check_journal_wrap(lh1.lh_sequence,
+						   &highest_seq);
+				print_gfs2("0x%llx (j+%4llx): Log header: "
+					   "Flags:%x, Seq: 0x%x, "
+					   "1st: 0x%x, tail: 0x%x, "
+					   "last: 0x%x", abs_block,
+					   jb, lh1.lh_flags, lh1.lh_sequence,
+					   lh1.lh_first, lh1.lh_tail,
+					   lh1.lh_last_dump);
+			} else {
+				gfs2_log_header_in(&lh, &dummy_bh);
+				check_journal_wrap(lh.lh_sequence,
+						   &highest_seq);
+				print_gfs2("0x%llx (j+%4llx): Log header: Seq"
+					   ": 0x%x, tail: 0x%x, blk: 0x%x",
+					   abs_block,
+					   jb / sbd.bsize, lh.lh_sequence,
+					   lh.lh_tail, lh.lh_blkno);
+			}
+			eol(0);
+		} else if (sbd.gfs1 && ld_blocks > 0) {
+			print_gfs2("0x%llx (j+%4llx): GFS log descriptor"
+				   " continuation block", abs_block, jb);
+			eol(0);
+			print_gfs2("                    ");
+			ld_blocks -= print_ld_blocks((uint64_t *)dummy_bh.b_data,
+						     (dummy_bh.b_data +
+						      sbd.bsize), start_line);
+		} else if (details && is_meta(&dummy_bh)) {
+			saveblk = block;
+			block = abs_block;
+			display(0);
+			block = saveblk;
+		}
+	}
+	inode_put(&j_inode);
+	brelse(j_bh);
+	blockhist = -1; /* So we don't print anything else */
+	free(jbuf);
+}
diff --git a/gfs2/edit/journal.h b/gfs2/edit/journal.h
new file mode 100644
index 0000000..e227a77
--- /dev/null
+++ b/gfs2/edit/journal.h
@@ -0,0 +1,8 @@
+#ifndef __JOURNAL_DOT_H__
+#define __JOURNAL_DOT_H__
+
+extern void dump_journal(const char *journal);
+extern uint64_t find_journal_block(const char *journal, uint64_t *j_size);
+
+
+#endif


More information about the cluster-commits mailing list