logdump.c revision 4bb0c0434c06da97836a3efba8a978a0d1ad5c6e
1da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o/*
2da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * logdump.c --- dump the contents of the journal out to a file
3da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o *
4da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * Authro: Stephen C. Tweedie, 2001  <sct@redhat.com>
5da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * Copyright (C) 2001 Red Hat, Inc.
6da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * Based on portions  Copyright (C) 1994 Theodore Ts'o.
7da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o *
8da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * This file may be redistributed under the terms of the GNU Public
9da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o * License.
10da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o */
11da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
12da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <stdio.h>
13da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <unistd.h>
14da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <stdlib.h>
15da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <ctype.h>
16da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <string.h>
17da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <time.h>
18da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#ifdef HAVE_ERRNO_H
19da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <errno.h>
20da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#endif
21da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <sys/types.h>
22da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <sys/stat.h>
23da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <fcntl.h>
24da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <utime.h>
25da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#ifdef HAVE_GETOPT_H
26da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include <getopt.h>
27da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#else
28da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oextern int optind;
29da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oextern char *optarg;
30da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#endif
31da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#ifdef HAVE_OPTRESET
32da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oextern int optreset;		/* defined by BSD, but not others */
33da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#endif
34da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
35da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include "debugfs.h"
36da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#include "jfs_user.h"
37da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
38da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oenum journal_location {JOURNAL_IS_INTERNAL, JOURNAL_IS_EXTERNAL};
39da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
40da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oint		dump_all, dump_contents, dump_descriptors;
41da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ounsigned int	block_to_dump, group_to_dump, bitmap_to_dump;
42da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ounsigned int	inode_block_to_dump, inode_offset_to_dump, bitmap_to_dump;
43da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oext2_ino_t	inode_to_dump;
44da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
45da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostruct journal_source
46da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
47da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	enum journal_location where;
48da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int fd;
49da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	ext2_file_t file;
50da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o};
51da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
52da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_journal(char *, FILE *, struct journal_source *);
53da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
54da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_descriptor_block(FILE *, struct journal_source *,
55da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  char *, journal_superblock_t *,
56da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  unsigned int *, int, tid_t);
57da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
58da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_revoke_block(FILE *, char *, journal_superblock_t *,
59da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  unsigned int, int, tid_t);
60da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
61da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_metadata_block(FILE *, struct journal_source *,
62da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				journal_superblock_t*,
63da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				unsigned int, unsigned int, int, tid_t);
64da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
65da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void do_hexdump (FILE *, char *, int);
66da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
67da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#define WRAP(jsb, blocknr)					\
68da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (blocknr >= be32_to_cpu((jsb)->s_maxlen))		\
69da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		blocknr -= (be32_to_cpu((jsb)->s_maxlen) -	\
70da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			    be32_to_cpu((jsb)->s_first));
71da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
72da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
73da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ovoid do_logdump(int argc, char **argv)
74da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
75da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	ext2_ino_t	inode;
76da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int		c;
77da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int		fd;
78da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int		retval;
79da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char		*out_fn;
80da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	FILE		*out_file;
81da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
82da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char		*inode_spec = NULL;
83da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char		*journal_fn = NULL;
84da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int		journal_fd = 0;
85da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	ext2_ino_t	journal_inum;
86da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	struct ext2_inode journal_inode;
87da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	ext2_file_t 	journal_file;
88da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
89da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char		*tmp;
90da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
91da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	const char	*logdump_usage = ("Usage: logdump "
92da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					  "[-ac] [-b<block>] [-i<inode>] "
93da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					  "[-f<journal_file>] [output_file]");
94da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
95da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	struct journal_source journal_source = {};
96da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
97da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	optind = 0;
98da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#ifdef HAVE_OPTRESET
99da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	optreset = 1;		/* Makes BSD getopt happy */
100da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o#endif
101da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	dump_all = 0;
102da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	dump_contents = 0;
103da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	dump_descriptors = 1;
104da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	block_to_dump = -1;
105da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	bitmap_to_dump = -1;
106da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	inode_block_to_dump = -1;
107da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	inode_to_dump = -1;
108da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
109da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	while ((c = getopt (argc, argv, "ab:ci:f:")) != EOF) {
110da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		switch (c) {
111da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case 'a':
112da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_all++;
113da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
114da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case 'b':
115da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			block_to_dump = strtoul(optarg, &tmp, 0);
116da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			if (*tmp) {
117da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				com_err(argv[0], 0,
118da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					"Bad block number - %s", optarg);
119da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				return;
120da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			}
121da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_descriptors = 0;
122da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
123da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case 'c':
124da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_contents++;
125da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
126da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case 'f':
127da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			journal_fn = optarg;
128da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
129da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case 'i':
130da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			inode_spec = optarg;
131da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_descriptors = 0;
132da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
133da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		default:
134da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], 0, logdump_usage);
135da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
136da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
137da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
138da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (optind != argc && optind != argc-1) {
139da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		com_err(argv[0], 0, logdump_usage);
140da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
141da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
142da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
143da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (inode_spec) {
144da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		int inode_group, group_offset, inodes_per_block;
145da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
146da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (check_fs_open(argv[0]))
147da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
148da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
149da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inode_to_dump = string_to_inode(inode_spec);
150da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (!inode_to_dump)
151da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
152da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
153da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inode_group = ((inode_to_dump - 1)
154da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			       / current_fs->super->s_inodes_per_group);
155da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		group_offset = ((inode_to_dump - 1)
156da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				% current_fs->super->s_inodes_per_group);
157da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inodes_per_block = (current_fs->blocksize
158da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    / sizeof(struct ext2_inode));
159da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
160da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inode_block_to_dump =
161da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			current_fs->group_desc[inode_group].bg_inode_table +
162da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			(group_offset / inodes_per_block);
163da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inode_offset_to_dump = ((group_offset % inodes_per_block)
164da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					* sizeof(struct ext2_inode));
165da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		printf("Inode %u is at group %u, block %u, offset %u\n",
166da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		       inode_to_dump, inode_group,
167da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		       inode_block_to_dump, inode_offset_to_dump);
168da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
169da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
170da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (optind == argc) {
171da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		out_file = stdout;
172da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	} else {
173da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		out_fn = argv[optind];
174da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		out_file = fopen(out_fn, "w");
175da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (!out_file < 0) {
176da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], errno, "while opening %s for logdump",
177da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				out_fn);
178da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
179da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
180da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
181da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
182da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (block_to_dump != -1 && current_fs != NULL) {
183da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		group_to_dump = ((block_to_dump -
184da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  current_fs->super->s_first_data_block)
185da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 / current_fs->super->s_blocks_per_group);
186da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		bitmap_to_dump = current_fs->group_desc[group_to_dump].bg_block_bitmap;
187da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
188da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
189da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (journal_fn) {
190da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
191da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* Set up to read journal from a regular file somewhere */
192da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_fd = open(journal_fn, O_RDONLY, 0);
193da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (journal_fd < 0) {
194da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], errno, "while opening %s for logdump",
195da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				journal_fn);
196da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
197da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
198da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
199da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_source.where = JOURNAL_IS_EXTERNAL;
200da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_source.fd = journal_fd;
201da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
202da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	} else {
203da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
204da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* Set up to read journal from the open filesystem */
205da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (check_fs_open(argv[0]))
206da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
207da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_inum = current_fs->super->s_journal_inum;
208da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (!journal_inum) {
209da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], 0, "filesystem has no journal");
210da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
211da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
212da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
213da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = ext2fs_read_inode(current_fs, journal_inum,
214da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					   &journal_inode);
215da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (retval) {
216da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], retval,
217da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				"while reading inode %u", journal_inum);
218da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
219da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
220da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
221da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = ext2fs_file_open(current_fs, journal_inum,
222da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					  0, &journal_file);
223da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (retval) {
224da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(argv[0], retval, "while opening ext2 file");
225da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
226da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
227da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
228da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_source.where = JOURNAL_IS_INTERNAL;
229da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		journal_source.file = journal_file;
230da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
231da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
232da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	dump_journal(argv[0], out_file, &journal_source);
233da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
234da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (journal_source.where == JOURNAL_IS_INTERNAL)
235da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		ext2fs_file_close(journal_file);
236da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	else
237da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		close(journal_fd);
238da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
239da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (out_file != stdout)
240da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fclose(out_file);
241da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
242da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	return;
243da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
244da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
245da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
246da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'oint read_journal_block(char *cmd, struct journal_source *source, off_t offset,
247da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		       char *buf, int size, int *got)
248da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
249da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int retval;
250da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
251da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (source->where == JOURNAL_IS_EXTERNAL) {
2524bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o		if (lseek(source->fd, offset, SEEK_SET) < 0) {
2534bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o			retval = errno;
2544bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o			com_err(cmd, retval, "while seeking in reading journal");
2554bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o			return retval;
2564bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o		}
2574bb0c0434c06da97836a3efba8a978a0d1ad5c6eTheodore Ts'o		retval = read(source->fd, buf, size);
258da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (retval >= 0) {
259da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			*got = retval;
260da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			retval = 0;
261da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
262da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = errno;
263da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	} else {
264da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = ext2fs_file_lseek(source->file, offset,
265da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					   EXT2_SEEK_SET, NULL);
266da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (retval) {
267da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			com_err(cmd, retval, "while seeking in reading journal");
268da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return retval;
269da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
270da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
271da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = ext2fs_file_read(source->file, buf, size, got);
272da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
273da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
274da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (retval)
275da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		com_err(cmd, retval, "while while reading journal");
276da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	else if (*got != size) {
277da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		com_err(cmd, 0, "short read (read %d, expected %d) while while reading journal", *got, size);
278da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = -1;
279da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
280da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
281da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	return retval;
282da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
283da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
284da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic char *type_to_name(int btype)
285da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
286da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	switch (btype) {
287da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	case JFS_DESCRIPTOR_BLOCK:
288da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return "descriptor block";
289da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	case JFS_COMMIT_BLOCK:
290da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return "commit block";
291da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	case JFS_SUPERBLOCK_V1:
292da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return "V1 superblock";
293da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	case JFS_SUPERBLOCK_V2:
294da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return "V2 superblock";
295da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	case JFS_REVOKE_BLOCK:
296da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return "revoke table";
297da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	default:
298da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
299da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	return "unrecognised type";
300da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
301da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
302da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
303da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_journal(char *cmdname, FILE *out_file,
304da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			 struct journal_source *source)
305da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
306da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char			jsb_buffer[1024];
307da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char			buf[8192];
308da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	journal_superblock_t	*jsb;
309da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int			blocksize;
310da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int			got;
311da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int			retval;
312da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	__u32			magic, sequence, blocktype;
313da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	journal_header_t	*header;
314da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
315da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	tid_t			transaction;
316da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	unsigned int		blocknr;
317da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
318da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	/* First: locate the journal superblock */
319da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
320da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	retval = read_journal_block(cmdname, source, 0,
321da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    jsb_buffer, 1024, &got);
322da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (retval)
323da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
324da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
325da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	jsb = (journal_superblock_t *) jsb_buffer;
326da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	blocksize = be32_to_cpu(jsb->s_blocksize);
327da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	transaction = be32_to_cpu(jsb->s_sequence);
328da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	blocknr = be32_to_cpu(jsb->s_start);
329da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
330da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	fprintf(out_file, "Journal starts at block %u, transaction %u\n",
331da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		blocknr, transaction);
332da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
333da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (!blocknr)
334da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* Empty journal, nothing to do. */
335da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
336da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
337da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	while (1) {
338da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		retval = read_journal_block(cmdname, source,
339da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					    blocknr*blocksize, buf,
340da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					    blocksize, &got);
341da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (retval || got != blocksize)
342da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
343da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
344da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		header = (journal_header_t *) buf;
345da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
346da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		magic = be32_to_cpu(header->h_magic);
347da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		sequence = be32_to_cpu(header->h_sequence);
348da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		blocktype = be32_to_cpu(header->h_blocktype);
349da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
350da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (magic != JFS_MAGIC_NUMBER) {
351da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf (out_file, "No magic number at block %u: "
352da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 "end of journal.\n", blocknr);
353da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
354da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
355da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
356da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (sequence != transaction) {
357da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf (out_file, "Found sequence %u (not %u) at "
358da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 "block %u: end of journal.\n",
359da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 sequence, transaction, blocknr);
360da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
361da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
362da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
363da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (dump_descriptors) {
364da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf (out_file, "Found expected sequence %u, "
365da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 "type %u (%s) at block %u\n",
366da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 sequence, blocktype,
367da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 type_to_name(blocktype), blocknr);
368da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
369da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
370da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		switch (blocktype) {
371da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case JFS_DESCRIPTOR_BLOCK:
372da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_descriptor_block(out_file, source, buf, jsb,
373da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					      &blocknr, blocksize,
374da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					      transaction);
375da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			continue;
376da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
377da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case JFS_COMMIT_BLOCK:
378da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			transaction++;
379da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			blocknr++;
380da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			WRAP(jsb, blocknr);
381da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			continue;
382da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
383da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		case JFS_REVOKE_BLOCK:
384da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			dump_revoke_block(out_file, buf, jsb,
385da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					  blocknr, blocksize,
386da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					  transaction);
387da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			blocknr++;
388da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			WRAP(jsb, blocknr);
389da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			continue;
390da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
391da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		default:
392da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf (out_file, "Unexpected block type %u at "
393da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				 "block %u.\n", blocktype, blocknr);
394da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			return;
395da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
396da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
397da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
398da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
399da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
400da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_descriptor_block(FILE *out_file,
401da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  struct journal_source *source,
402da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  char *buf,
403da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  journal_superblock_t *jsb,
404da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  unsigned int *blockp, int blocksize,
405da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  tid_t transaction)
406da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
407da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int			offset;
408da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char			*tagp;
409da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	journal_block_tag_t	*tag;
410da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	unsigned int		blocknr;
411da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	__u32			tag_block;
412da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	__u32			tag_flags;
413da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
414da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
415da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	offset = sizeof(journal_header_t);
416da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	blocknr = *blockp;
417da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
418da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (dump_all)
419da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "Dumping descriptor block, sequence %u, at "
420da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			"block %u:\n", transaction, blocknr);
421da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
422da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	++blocknr;
423da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	WRAP(jsb, blocknr);
424da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
425da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	do {
426da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* Work out the location of the current tag, and skip to
427da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		 * the next one... */
428da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		tagp = &buf[offset];
429da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		tag = (journal_block_tag_t *) tagp;
430da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		offset += sizeof(journal_block_tag_t);
431da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
432da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* ... and if we have gone too far, then we've reached the
433da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		   end of this block. */
434da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (offset > blocksize)
435da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			break;
436da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
437da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		tag_block = be32_to_cpu(tag->t_blocknr);
438da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		tag_flags = be32_to_cpu(tag->t_flags);
439da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
440da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (!(tag_flags & JFS_FLAG_SAME_UUID))
441da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			offset += 16;
442da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
443da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		dump_metadata_block(out_file, source, jsb,
444da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    blocknr, tag_block, blocksize,
445da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    transaction);
446da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
447da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		++blocknr;
448da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		WRAP(jsb, blocknr);
449da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
450da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	} while (!(tag_flags & JFS_FLAG_LAST_TAG));
451da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
452da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	*blockp = blocknr;
453da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
454da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
455da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
456da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_revoke_block(FILE *out_file, char *buf,
457da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  journal_superblock_t *jsb,
458da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  unsigned int blocknr, int blocksize,
459da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				  tid_t transaction)
460da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
461da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int			offset, max;
462da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	journal_revoke_header_t *header;
463da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	unsigned int		*entry, rblock;
464da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
465da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (dump_all)
466da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "Dumping revoke block, sequence %u, at "
467da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			"block %u:\n", transaction, blocknr);
468da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
469da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	header = (journal_revoke_header_t *) buf;
470da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	offset = sizeof(journal_revoke_header_t);
471da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	max = be32_to_cpu(header->r_count);
472da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
473da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	while (offset < max) {
474da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		entry = (unsigned int *) (buf + offset);
475da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		rblock = be32_to_cpu(*entry);
476da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		if (dump_all || rblock == block_to_dump) {
477da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf(out_file, "  Revoke FS block %u", rblock);
478da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			if (dump_all)
479da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				fprintf(out_file, "\n");
480da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			else
481da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				fprintf(out_file," at block %u, sequence %u\n",
482da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o					blocknr, transaction);
483da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
484da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		offset += 4;
485da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
486da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
487da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
488da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
489da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void show_extent(FILE *out_file, int start_extent, int end_extent,
490da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			__u32 first_block)
491da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
492da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (start_extent >= 0 && first_block != 0)
493da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "(%d+%u): %u ",
494da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			start_extent, end_extent-start_extent, first_block);
495da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
496da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
497da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void show_indirect(FILE *out_file, char *name, __u32 where)
498da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
499da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (where)
500da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "(%s): %u ", name, where);
501da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
502da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
503da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
504da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void dump_metadata_block(FILE *out_file, struct journal_source *source,
505da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				journal_superblock_t *jsb,
506da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				unsigned int log_blocknr,
507da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				unsigned int fs_blocknr,
508da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				int blocksize,
509da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				tid_t transaction)
510da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
511da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int got, retval;
512da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char buf[8192];
513da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
514da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (!(dump_all
515da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	      || (fs_blocknr == block_to_dump)
516da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	      || (fs_blocknr == inode_block_to_dump)
517da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	      || (fs_blocknr == bitmap_to_dump)))
518da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
519da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
520da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	fprintf(out_file, "  FS block %u logged at ", fs_blocknr);
521da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (!dump_all)
522da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "sequence %u, ", transaction);
523da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	fprintf(out_file, "journal block %u\n", log_blocknr);
524da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
525da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	/* There are two major special cases to parse:
526da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 *
527da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * If this block is a block
528da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * bitmap block, we need to give it special treatment so that we
529da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * can log any allocates and deallocates which affect the
530da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * block_to_dump query block.
531da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 *
532da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * If the block is an inode block for the inode being searched
533da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * for, then we need to dump the contents of that inode
534da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 * structure symbolically.
535da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	 */
536da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
537da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (!(dump_contents && dump_all)
538da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	    && fs_blocknr != block_to_dump
539da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	    && fs_blocknr != bitmap_to_dump
540da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	    && fs_blocknr != inode_block_to_dump)
541da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
542da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
543da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	retval = read_journal_block("logdump", source,
544da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    blocksize * log_blocknr,
545da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				    buf, blocksize, &got);
546da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (retval)
547da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		return;
548da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
549da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (fs_blocknr == bitmap_to_dump) {
550da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		struct ext2_super_block *super;
551da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		int offset;
552da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
553da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		super = current_fs->super;
554da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		offset = ((fs_blocknr - super->s_first_data_block) %
555da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			  super->s_blocks_per_group);
556da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
557da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "    (block bitmap for block %u: "
558da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			"block is %s)\n",
559da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			block_to_dump,
560da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			ext2fs_test_bit(offset, buf) ? "SET" : "CLEAR");
561da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
562da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
563da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (fs_blocknr == inode_block_to_dump) {
564da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		struct ext2_inode *inode;
565da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		int first, prev, this, start_extent, i;
566da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
567da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "    (inode block for inode %u):\n",
568da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			inode_to_dump);
569da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
570da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		inode = (struct ext2_inode *) (buf + inode_offset_to_dump);
571da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		internal_dump_inode(out_file, "    ", inode_to_dump, inode, 0);
572da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
573da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		/* Dump out the direct/indirect blocks here:
574da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		 * internal_dump_inode can only dump them from the main
575da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		 * on-disk inode, not from the journaled copy of the
576da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		 * inode. */
577da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
578da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf (out_file, "    Blocks:  ");
579da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		start_extent = -1;
580da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
581da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		for (i=0; i<EXT2_NDIR_BLOCKS; i++) {
582da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			this = inode->i_block[i];
583da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			if (start_extent >= 0  && this == prev+1) {
584da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				prev = this;
585da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				continue;
586da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			} else {
587da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				show_extent(out_file, start_extent, i, first);
588da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				start_extent = i;
589da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				first = prev = this;
590da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			}
591da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
592da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		show_extent(out_file, start_extent, i, first);
593da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		show_indirect(out_file, "IND", inode->i_block[i++]);
594da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		show_indirect(out_file, "DIND", inode->i_block[i++]);
595da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		show_indirect(out_file, "TIND", inode->i_block[i++]);
596da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
597da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "\n");
598da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
599da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
600da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	if (dump_contents)
601da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		do_hexdump(out_file, buf, blocksize);
602da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
603da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
604da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
605da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'ostatic void do_hexdump (FILE *out_file, char *buf, int blocksize)
606da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o{
607da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int i,j;
608da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	int *intp;
609da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	char *charp;
610da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	unsigned char c;
611da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
612da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	intp = (int *) buf;
613da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	charp = (char *) buf;
614da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
615da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	for (i=0; i<blocksize; i+=16) {
616da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "    %04x:  ", i);
617da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		for (j=0; j<16; j+=4)
618da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf(out_file, "%08x ", *intp++);
619da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		for (j=0; j<16; j++) {
620da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			c = *charp++;
621da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			if (c < ' ' || c >= 127)
622da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o				c = '.';
623da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o			fprintf(out_file, "%c", c);
624da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		}
625da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o		fprintf(out_file, "\n");
626da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o	}
627da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o}
628da81e3fcfe075922e995a1c5f1efded5768d519aTheodore Ts'o
629