Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=478f093f...
Commit: 478f093f301149c54db72a94ff7e9148ac00444e
Parent: 57f0e1b70dbd1de7aca9b2bdc09d49d28c25d888
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Feb 27 09:23:04 2014 -0500
Committer: Andrew Price <anprice(a)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(a)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, ¬_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, ¬_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