]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - logprint/log_misc.c
xfs_logprint: fix shadow var in xlog_print_trans_buffer
[thirdparty/xfsprogs-dev.git] / logprint / log_misc.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18 5 */
6b803e5a
CH
6#include "libxfs.h"
7#include "libxlog.h"
2bd0ea18
NS
8
9#include "logprint.h"
10
dfb5b7da 11#define CLEARED_BLKS (-5)
2bd0ea18
NS
12#define ZEROED_LOG (-4)
13#define FULL_READ (-3)
14#define PARTIAL_READ (-2)
15#define BAD_HEADER (-1)
16#define NO_ERROR (0)
17
18static int logBBsize;
2bd0ea18
NS
19
20typedef struct xlog_split_item {
21 struct xlog_split_item *si_next;
22 struct xlog_split_item *si_prev;
58d0d840 23 xlog_tid_t si_xtid;
2bd0ea18
NS
24 int si_skip;
25} xlog_split_item_t;
26
00ff2b10 27static xlog_split_item_t *split_list = NULL;
2bd0ea18
NS
28
29void
30print_xlog_op_line(void)
31{
32 printf("--------------------------------------"
dfc130f3 33 "--------------------------------------\n");
2bd0ea18
NS
34} /* print_xlog_op_line */
35
00ff2b10 36static void
dfb5b7da 37print_xlog_xhdr_line(void)
38{
39 printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
40 "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
41} /* print_xlog_xhdr_line */
42
2bd0ea18
NS
43void
44print_xlog_record_line(void)
45{
46 printf("======================================"
dfc130f3 47 "======================================\n");
2bd0ea18
NS
48} /* print_xlog_record_line */
49
50void
51print_stars(void)
52{
53 printf("***********************************"
dfc130f3 54 "***********************************\n");
dfb5b7da 55} /* print_stars */
2bd0ea18
NS
56
57/*
58 * Given a pointer to a data segment, print out the data as if it were
59 * a log operation header.
60 */
00ff2b10 61static void
2bd0ea18
NS
62xlog_print_op_header(xlog_op_header_t *op_head,
63 int i,
d60ba955 64 char **ptr)
2bd0ea18
NS
65{
66 xlog_op_header_t hbuf;
67
68 /*
dab9b8d6 69 * memmove because on 64/n32, partial reads can cause the op_head
2bd0ea18
NS
70 * pointer to come in pointing to an odd-numbered byte
71 */
dab9b8d6 72 memmove(&hbuf, op_head, sizeof(xlog_op_header_t));
2bd0ea18
NS
73 op_head = &hbuf;
74 *ptr += sizeof(xlog_op_header_t);
9ee7055c 75 printf(_("Oper (%d): tid: %x len: %d clientid: %s "), i,
5e656dbb
BN
76 be32_to_cpu(op_head->oh_tid),
77 be32_to_cpu(op_head->oh_len),
2bd0ea18
NS
78 (op_head->oh_clientid == XFS_TRANSACTION ? "TRANS" :
79 (op_head->oh_clientid == XFS_LOG ? "LOG" : "ERROR")));
9ee7055c 80 printf(_("flags: "));
2bd0ea18
NS
81 if (op_head->oh_flags) {
82 if (op_head->oh_flags & XLOG_START_TRANS)
83 printf("START ");
84 if (op_head->oh_flags & XLOG_COMMIT_TRANS)
85 printf("COMMIT ");
86 if (op_head->oh_flags & XLOG_WAS_CONT_TRANS)
87 printf("WAS_CONT ");
88 if (op_head->oh_flags & XLOG_UNMOUNT_TRANS)
89 printf("UNMOUNT ");
90 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
91 printf("CONTINUE ");
92 if (op_head->oh_flags & XLOG_END_TRANS)
93 printf("END ");
94 } else {
9ee7055c 95 printf(_("none"));
2bd0ea18
NS
96 }
97 printf("\n");
98} /* xlog_print_op_header */
99
100
00ff2b10 101static void
2bd0ea18
NS
102xlog_print_add_to_trans(xlog_tid_t tid,
103 int skip)
104{
105 xlog_split_item_t *item;
106
107 item = (xlog_split_item_t *)calloc(sizeof(xlog_split_item_t), 1);
58d0d840 108 item->si_xtid = tid;
2bd0ea18
NS
109 item->si_skip = skip;
110 item->si_next = split_list;
5e656dbb 111 item->si_prev = NULL;
2bd0ea18
NS
112 if (split_list)
113 split_list->si_prev = item;
114 split_list = item;
115} /* xlog_print_add_to_trans */
116
117
00ff2b10 118static int
2bd0ea18
NS
119xlog_print_find_tid(xlog_tid_t tid, uint was_cont)
120{
121 xlog_split_item_t *listp = split_list;
122
123 if (!split_list) {
124 if (was_cont != 0) /* Not first time we have used this tid */
125 return 1;
126 else
127 return 0;
128 }
129 while (listp) {
58d0d840 130 if (listp->si_xtid == tid)
2bd0ea18
NS
131 break;
132 listp = listp->si_next;
133 }
134 if (!listp) {
135 return 0;
136 }
137 if (--listp->si_skip == 0) {
138 if (listp == split_list) { /* delete at head */
139 split_list = listp->si_next;
140 if (split_list)
141 split_list->si_prev = NULL;
142 } else {
143 if (listp->si_next)
144 listp->si_next->si_prev = listp->si_prev;
145 listp->si_prev->si_next = listp->si_next;
146 }
147 free(listp);
148 }
149 return 1;
150} /* xlog_print_find_tid */
151
00ff2b10 152static int
d60ba955 153xlog_print_trans_header(char **ptr, int len)
2bd0ea18
NS
154{
155 xfs_trans_header_t *h;
d60ba955 156 char *cptr = *ptr;
14f8b681 157 uint32_t magic;
2bd0ea18
NS
158 char *magic_c = (char *)&magic;
159
160 *ptr += len;
dfc130f3 161
14f8b681 162 magic = *(uint32_t *)cptr; /* XXX be32_to_cpu soon */
dfc130f3 163
150a512d 164 if (len >= 4) {
2bd0ea18 165#if __BYTE_ORDER == __LITTLE_ENDIAN
dfc130f3
RC
166 printf("%c%c%c%c:",
167 magic_c[3], magic_c[2], magic_c[1], magic_c[0]);
2bd0ea18 168#else
dfc130f3
RC
169 printf("%c%c%c%c:",
170 magic_c[0], magic_c[1], magic_c[2], magic_c[3]);
2bd0ea18 171#endif
150a512d 172 }
2bd0ea18 173 if (len != sizeof(xfs_trans_header_t)) {
9ee7055c 174 printf(_(" Not enough data to decode further\n"));
2bd0ea18
NS
175 return 1;
176 }
177 h = (xfs_trans_header_t *)cptr;
4fd2b075
HT
178 printf(_(" tid: %x num_items: %d\n"),
179 h->th_tid, h->th_num_items);
2bd0ea18
NS
180 return 0;
181} /* xlog_print_trans_header */
182
183
00ff2b10 184static int
d60ba955 185xlog_print_trans_buffer(char **ptr, int len, int *i, int num_ops)
2bd0ea18
NS
186{
187 xfs_buf_log_format_t *f;
5e656dbb 188 xlog_op_header_t *head = NULL;
2bd0ea18
NS
189 int num, skip;
190 int super_block = 0;
191 int bucket, col, buckets;
14f8b681 192 int64_t blkno;
2bd0ea18
NS
193 xfs_buf_log_format_t lbuf;
194 int size, blen, map_size, struct_size;
919dbc78 195 unsigned short flags;
dfc130f3 196
2bd0ea18 197 /*
dab9b8d6 198 * memmove to ensure 8-byte alignment for the long longs in
2bd0ea18
NS
199 * buf_log_format_t structure
200 */
68d16907 201 memmove(&lbuf, *ptr, min(sizeof(xfs_buf_log_format_t), len));
2bd0ea18
NS
202 f = &lbuf;
203 *ptr += len;
204
5e656dbb
BN
205 ASSERT(f->blf_type == XFS_LI_BUF);
206 printf("BUF: ");
207 blkno = f->blf_blkno;
208 size = f->blf_size;
209 blen = f->blf_len;
210 map_size = f->blf_map_size;
211 flags = f->blf_flags;
8e78288a
DC
212
213 /*
214 * size of the format header is dependent on the size of the bitmap, not
215 * the size of the in-memory structure. Hence the slightly obtuse
216 * calculation.
217 */
218 struct_size = offsetof(struct xfs_buf_log_format, blf_map_size) + map_size;
5e656dbb 219
2bd0ea18
NS
220 if (len >= struct_size) {
221 ASSERT((len - sizeof(struct_size)) % sizeof(int) == 0);
9ee7055c 222 printf(_("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n"),
299173ff 223 size, (long long)blkno, (unsigned long long)blkno, blen, map_size, flags);
2bd0ea18
NS
224 if (blkno == 0)
225 super_block = 1;
226 } else {
227 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
9ee7055c 228 printf(_("#regs: %d Not printing rest of data\n"), f->blf_size);
2bd0ea18
NS
229 return size;
230 }
231 num = size-1;
232
233 /* Check if all regions in this log item were in the given LR ptr */
234 if (*i+num > num_ops-1) {
235 skip = num - (num_ops-1-*i);
236 num = num_ops-1-*i;
237 } else {
238 skip = 0;
239 }
240 while (num-- > 0) {
241 (*i)++;
242 head = (xlog_op_header_t *)*ptr;
243 xlog_print_op_header(head, *i, ptr);
244 if (super_block) {
9ee7055c 245 printf(_("SUPER BLOCK Buffer: "));
5e656dbb 246 if (be32_to_cpu(head->oh_len) < 4*8) {
9ee7055c 247 printf(_("Out of space\n"));
2bd0ea18 248 } else {
4add9d50
ES
249 __be64 a, b;
250
2bd0ea18
NS
251 printf("\n");
252 /*
dab9b8d6 253 * memmove because *ptr may not be 8-byte aligned
2bd0ea18 254 */
4add9d50
ES
255 memmove(&a, *ptr, sizeof(__be64));
256 memmove(&b, *ptr+8, sizeof(__be64));
257 printf(_("icount: %llu ifree: %llu "),
258 (unsigned long long) be64_to_cpu(a),
259 (unsigned long long) be64_to_cpu(b));
260 memmove(&a, *ptr+16, sizeof(__be64));
261 memmove(&b, *ptr+24, sizeof(__be64));
262 printf(_("fdblks: %llu frext: %llu\n"),
263 (unsigned long long) be64_to_cpu(a),
264 (unsigned long long) be64_to_cpu(b));
2bd0ea18
NS
265 }
266 super_block = 0;
5e656dbb 267 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGI_MAGIC) {
6f947c99
ES
268 struct xfs_agi *agi, agi_s;
269
270 /* memmove because *ptr may not be 8-byte aligned */
271 agi = &agi_s;
272 memmove(agi, *ptr, sizeof(struct xfs_agi));
9ee7055c 273 printf(_("AGI Buffer: XAGI "));
ba24eb7c
JK
274 /*
275 * v4 filesystems only contain the fields before the uuid.
276 * Even v5 filesystems don't log any field beneath it. That
277 * means that the size that is logged is almost always going to
278 * be smaller than the structure itself. Hence we need to make
279 * sure that the buffer contains all the data we want to print
280 * rather than just check against the structure size.
281 */
282 if (be32_to_cpu(head->oh_len) < offsetof(xfs_agi_t, agi_uuid) -
5e656dbb 283 XFS_AGI_UNLINKED_BUCKETS*sizeof(xfs_agino_t)) {
9ee7055c 284 printf(_("out of space\n"));
2bd0ea18
NS
285 } else {
286 printf("\n");
9ee7055c 287 printf(_("ver: %d "),
5e656dbb 288 be32_to_cpu(agi->agi_versionnum));
9ee7055c 289 printf(_("seq#: %d len: %d cnt: %d root: %d\n"),
5e656dbb
BN
290 be32_to_cpu(agi->agi_seqno),
291 be32_to_cpu(agi->agi_length),
292 be32_to_cpu(agi->agi_count),
293 be32_to_cpu(agi->agi_root));
9ee7055c 294 printf(_("level: %d free#: 0x%x newino: 0x%x\n"),
5e656dbb
BN
295 be32_to_cpu(agi->agi_level),
296 be32_to_cpu(agi->agi_freecount),
297 be32_to_cpu(agi->agi_newino));
298 if (be32_to_cpu(head->oh_len) == 128) {
2bd0ea18 299 buckets = 17;
5e656dbb 300 } else if (be32_to_cpu(head->oh_len) == 256) {
2bd0ea18
NS
301 buckets = 32 + 17;
302 } else {
c3cf3190 303 if (head->oh_flags & XLOG_CONTINUE_TRANS) {
9ee7055c
AM
304 printf(_("AGI unlinked data skipped "));
305 printf(_("(CONTINUE set, no space)\n"));
c3cf3190
NS
306 continue;
307 }
2bd0ea18
NS
308 buckets = XFS_AGI_UNLINKED_BUCKETS;
309 }
310 for (bucket = 0; bucket < buckets;) {
9ee7055c 311 printf(_("bucket[%d - %d]: "), bucket, bucket+3);
2bd0ea18
NS
312 for (col = 0; col < 4; col++, bucket++) {
313 if (bucket < buckets) {
314 printf("0x%x ",
5e656dbb 315 be32_to_cpu(agi->agi_unlinked[bucket]));
2bd0ea18
NS
316 }
317 }
318 printf("\n");
319 }
320 }
5e656dbb 321 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGF_MAGIC) {
6f947c99
ES
322 struct xfs_agf *agf, agf_s;
323
324 /* memmove because *ptr may not be 8-byte aligned */
325 agf = &agf_s;
326 memmove(agf, *ptr, sizeof(struct xfs_agf));
9ee7055c 327 printf(_("AGF Buffer: XAGF "));
ba24eb7c
JK
328 /*
329 * v4 filesystems only contain the fields before the uuid.
330 * Even v5 filesystems don't log any field beneath it. That
331 * means that the size that is logged is almost always going to
332 * be smaller than the structure itself. Hence we need to make
333 * sure that the buffer contains all the data we want to print
334 * rather than just check against the structure size.
335 */
336 if (be32_to_cpu(head->oh_len) < offsetof(xfs_agf_t, agf_uuid)) {
9ee7055c 337 printf(_("Out of space\n"));
2bd0ea18
NS
338 } else {
339 printf("\n");
9ee7055c 340 printf(_("ver: %d seq#: %d len: %d \n"),
5e656dbb
BN
341 be32_to_cpu(agf->agf_versionnum),
342 be32_to_cpu(agf->agf_seqno),
343 be32_to_cpu(agf->agf_length));
9ee7055c 344 printf(_("root BNO: %d CNT: %d\n"),
5e656dbb
BN
345 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]),
346 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
9ee7055c 347 printf(_("level BNO: %d CNT: %d\n"),
5e656dbb
BN
348 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]),
349 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
9ee7055c
AM
350 printf(_("1st: %d last: %d cnt: %d "
351 "freeblks: %d longest: %d\n"),
5e656dbb
BN
352 be32_to_cpu(agf->agf_flfirst),
353 be32_to_cpu(agf->agf_fllast),
354 be32_to_cpu(agf->agf_flcount),
355 be32_to_cpu(agf->agf_freeblks),
356 be32_to_cpu(agf->agf_longest));
2bd0ea18 357 }
5e656dbb 358 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_DQUOT_MAGIC) {
6f947c99
ES
359 struct xfs_disk_dquot *dq, dq_s;
360
361 /* memmove because *ptr may not be 8-byte aligned */
362 dq = &dq_s;
363 memmove(dq, *ptr, sizeof(struct xfs_disk_dquot));
9ee7055c 364 printf(_("DQUOT Buffer: DQ "));
5e656dbb 365 if (be32_to_cpu(head->oh_len) <
2bd0ea18 366 sizeof(xfs_disk_dquot_t)) {
9ee7055c 367 printf(_("Out of space\n"));
2bd0ea18
NS
368 }
369 else {
370 printf("\n");
9ee7055c 371 printf(_("ver: %d flags: 0x%x id: %d \n"),
5e656dbb
BN
372 dq->d_version, dq->d_flags,
373 be32_to_cpu(dq->d_id));
9ee7055c 374 printf(_("blk limits hard: %llu soft: %llu\n"),
f934f4a5
AE
375 (unsigned long long)
376 be64_to_cpu(dq->d_blk_hardlimit),
377 (unsigned long long)
378 be64_to_cpu(dq->d_blk_softlimit));
9ee7055c 379 printf(_("blk count: %llu warns: %d timer: %d\n"),
f934f4a5
AE
380 (unsigned long long) be64_to_cpu(dq->d_bcount),
381 (int) be16_to_cpu(dq->d_bwarns),
5e656dbb 382 be32_to_cpu(dq->d_btimer));
9ee7055c 383 printf(_("ino limits hard: %llu soft: %llu\n"),
f934f4a5
AE
384 (unsigned long long)
385 be64_to_cpu(dq->d_ino_hardlimit),
386 (unsigned long long)
387 be64_to_cpu(dq->d_ino_softlimit));
9ee7055c 388 printf(_("ino count: %llu warns: %d timer: %d\n"),
f934f4a5
AE
389 (unsigned long long) be64_to_cpu(dq->d_icount),
390 (int) be16_to_cpu(dq->d_iwarns),
5e656dbb 391 be32_to_cpu(dq->d_itimer));
2bd0ea18
NS
392 }
393 } else {
9ee7055c 394 printf(_("BUF DATA\n"));
2bd0ea18
NS
395 if (print_data) {
396 uint *dp = (uint *)*ptr;
5e656dbb 397 int nums = be32_to_cpu(head->oh_len) >> 2;
4a706e03 398 int byte = 0;
2bd0ea18 399
4a706e03
ES
400 while (byte < nums) {
401 if ((byte % 8) == 0)
402 printf("%2x ", byte);
2bd0ea18
NS
403 printf("%8x ", *dp);
404 dp++;
4a706e03
ES
405 byte++;
406 if ((byte % 8) == 0)
2bd0ea18
NS
407 printf("\n");
408 }
409 printf("\n");
410 }
411 }
5e656dbb 412 *ptr += be32_to_cpu(head->oh_len);
2bd0ea18
NS
413 }
414 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
415 skip++;
416 return skip;
417} /* xlog_print_trans_buffer */
418
419
00ff2b10 420static int
d60ba955 421xlog_print_trans_qoff(char **ptr, uint len)
c3cf3190
NS
422{
423 xfs_qoff_logformat_t *f;
424 xfs_qoff_logformat_t lbuf;
425
68d16907 426 memmove(&lbuf, *ptr, min(sizeof(xfs_qoff_logformat_t), len));
c3cf3190
NS
427 f = &lbuf;
428 *ptr += len;
429 if (len >= sizeof(xfs_qoff_logformat_t)) {
9ee7055c 430 printf(_("QOFF: #regs: %d flags: 0x%x\n"), f->qf_size, f->qf_flags);
c3cf3190
NS
431 return 0;
432 } else {
9ee7055c 433 printf(_("QOFF: Not enough data to decode further\n"));
c3cf3190
NS
434 return 1;
435 }
436} /* xlog_print_trans_qoff */
437
438
00ff2b10 439static void
138659f1
DC
440xlog_print_trans_inode_core(
441 struct xfs_log_dinode *ip)
2bd0ea18 442{
9ee7055c
AM
443 printf(_("INODE CORE\n"));
444 printf(_("magic 0x%hx mode 0%ho version %d format %d\n"),
2bd0ea18
NS
445 ip->di_magic, ip->di_mode, (int)ip->di_version,
446 (int)ip->di_format);
9ee7055c 447 printf(_("nlink %hd uid %d gid %d\n"),
2bd0ea18 448 ip->di_nlink, ip->di_uid, ip->di_gid);
9ee7055c 449 printf(_("atime 0x%x mtime 0x%x ctime 0x%x\n"),
2bd0ea18 450 ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec);
9ee7055c 451 printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"),
5b64e00a
NS
452 (unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
453 ip->di_extsize, ip->di_nextents);
9ee7055c 454 printf(_("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n"),
2bd0ea18
NS
455 ip->di_anextents, (int)ip->di_forkoff, ip->di_dmevmask,
456 ip->di_dmstate);
9ee7055c 457 printf(_("flags 0x%x gen 0x%x\n"),
2bd0ea18 458 ip->di_flags, ip->di_gen);
1fe708d6
DW
459 if (ip->di_version == 3) {
460 printf(_("flags2 0x%llx cowextsize 0x%x\n"),
461 (unsigned long long)ip->di_flags2, ip->di_cowextsize);
462 }
2bd0ea18
NS
463}
464
00ff2b10 465static void
494434d7
DC
466xlog_print_dir2_sf(
467 struct xlog *log,
468 xfs_dir2_sf_hdr_t *sfp,
469 int size)
2bd0ea18 470{
8e1338fb 471 __be64 pino; /* parent inode nr */
2bd0ea18
NS
472 xfs_ino_t ino;
473 int count;
474 int i;
475 char namebuf[257];
9a048535 476 xfs_dir2_sf_entry_t *sfep;
2bd0ea18 477
9ee7055c 478 printf(_("SHORTFORM DIRECTORY size %d\n"),
dfc130f3
RC
479 size);
480 /* bail out for now */
481
482 return;
483
9ee7055c 484 printf(_("SHORTFORM DIRECTORY size %d count %d\n"),
a2ceac1f 485 size, sfp->count);
8e1338fb
ES
486 memmove(&pino, &(sfp->parent), sizeof(pino));
487 printf(_(".. ino 0x%llx\n"), (unsigned long long) be64_to_cpu(pino));
2bd0ea18 488
a2ceac1f
DC
489 count = sfp->count;
490 sfep = xfs_dir2_sf_firstentry(sfp);
2bd0ea18 491 for (i = 0; i < count; i++) {
ff105f75 492 ino = M_DIROPS(log->l_mp)->sf_get_ino(sfp, sfep);
dab9b8d6 493 memmove(namebuf, (sfep->name), sfep->namelen);
2bd0ea18 494 namebuf[sfep->namelen] = '\0';
9ee7055c 495 printf(_("%s ino 0x%llx namelen %d\n"),
5b64e00a 496 namebuf, (unsigned long long)ino, sfep->namelen);
ff105f75 497 sfep = M_DIROPS(log->l_mp)->sf_nextentry(sfp, sfep);
2bd0ea18
NS
498 }
499}
500
00ff2b10 501static int
494434d7 502xlog_print_trans_inode(
87daa553
DC
503 struct xlog *log,
504 char **ptr,
505 int len,
506 int *i,
507 int num_ops,
508 int continued)
2bd0ea18 509{
87daa553
DC
510 struct xfs_log_dinode dino;
511 struct xlog_op_header *op_head;
512 struct xfs_inode_log_format dst_lbuf;
513 struct xfs_inode_log_format src_lbuf;
514 struct xfs_inode_log_format *f;
515 int mode;
516 int size;
517 int skip_count;
2bd0ea18
NS
518
519 /*
520 * print inode type header region
521 *
dab9b8d6 522 * memmove to ensure 8-byte alignment for the long longs in
e784bcd5 523 * struct xfs_inode_log_format structure
2bd0ea18 524 *
e784bcd5 525 * len can be smaller than struct xfs_inode_log_format
299173ff 526 * if format data is split over operations
2bd0ea18 527 */
68d16907 528 memmove(&src_lbuf, *ptr, min(sizeof(src_lbuf), len));
2bd0ea18
NS
529 (*i)++; /* bump index */
530 *ptr += len;
a8cfa1a4 531 if (!continued &&
87daa553
DC
532 (len == sizeof(struct xfs_inode_log_format_32) ||
533 len == sizeof(struct xfs_inode_log_format))) {
dab9b8d6 534 f = xfs_inode_item_format_convert((char*)&src_lbuf, len, &dst_lbuf);
9ee7055c
AM
535 printf(_("INODE: "));
536 printf(_("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n"),
299173ff
TS
537 f->ilf_size, (unsigned long long)f->ilf_ino,
538 f->ilf_fields, f->ilf_dsize);
9ee7055c 539 printf(_(" blkno: %lld len: %d boff: %d\n"),
299173ff 540 (long long)f->ilf_blkno, f->ilf_len, f->ilf_boffset);
2bd0ea18 541 } else {
299173ff 542 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
e784bcd5 543 f = (struct xfs_inode_log_format *)&src_lbuf;
9ee7055c 544 printf(_("INODE: #regs: %d Not printing rest of data\n"),
299173ff
TS
545 f->ilf_size);
546 return f->ilf_size;
2bd0ea18
NS
547 }
548
04f1d806
HT
549 skip_count = f->ilf_size-1;
550
2bd0ea18 551 if (*i >= num_ops) /* end of LR */
04f1d806 552 return skip_count;
2bd0ea18
NS
553
554 /* core inode comes 2nd */
555 op_head = (xlog_op_header_t *)*ptr;
556 xlog_print_op_header(op_head, *i, ptr);
dfc130f3 557
0e22d318 558 if (op_head->oh_flags & XLOG_CONTINUE_TRANS) {
04f1d806 559 return skip_count;
2bd0ea18 560 }
dfc130f3 561
dab9b8d6 562 memmove(&dino, *ptr, sizeof(dino));
322f2a29 563 mode = dino.di_mode & S_IFMT;
2bd0ea18
NS
564 size = (int)dino.di_size;
565 xlog_print_trans_inode_core(&dino);
138659f1 566 *ptr += xfs_log_dinode_size(dino.di_version);
04f1d806 567 skip_count--;
dda41291
ES
568
569 switch (f->ilf_fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
570 case XFS_ILOG_DEV:
571 printf(_("DEV inode: no extra region\n"));
572 break;
573 case XFS_ILOG_UUID:
574 printf(_("UUID inode: no extra region\n"));
575 break;
576 }
577
578 /* Only the inode core is logged */
579 if (f->ilf_size == 2)
580 return 0;
581
582 ASSERT(f->ilf_size <= 4);
583 ASSERT((f->ilf_size == 3) || (f->ilf_fields & XFS_ILOG_AFORK));
584
04f1d806
HT
585 /* does anything come next */
586 op_head = (xlog_op_header_t *)*ptr;
587
dda41291 588 if (f->ilf_fields & XFS_ILOG_DFORK) {
04f1d806
HT
589 if (*i == num_ops-1)
590 return skip_count;
a981f202
NS
591 (*i)++;
592 xlog_print_op_header(op_head, *i, ptr);
dda41291
ES
593
594 switch (f->ilf_fields & XFS_ILOG_DFORK) {
595 case XFS_ILOG_DEXT:
596 printf(_("EXTENTS inode data\n"));
597 break;
598 case XFS_ILOG_DBROOT:
599 printf(_("BTREE inode data\n"));
600 break;
601 case XFS_ILOG_DDATA:
602 printf(_("LOCAL inode data\n"));
603 if (mode == S_IFDIR)
494434d7 604 xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size);
dda41291
ES
605 break;
606 default:
607 ASSERT((f->ilf_fields & XFS_ILOG_DFORK) == 0);
608 break;
a981f202 609 }
dda41291 610
5e656dbb 611 *ptr += be32_to_cpu(op_head->oh_len);
0e22d318 612 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
04f1d806 613 return skip_count;
dda41291 614 op_head = (xlog_op_header_t *)*ptr;
04f1d806 615 skip_count--;
dda41291
ES
616 }
617
618 if (f->ilf_fields & XFS_ILOG_AFORK) {
04f1d806
HT
619 if (*i == num_ops-1)
620 return skip_count;
a981f202
NS
621 (*i)++;
622 xlog_print_op_header(op_head, *i, ptr);
dda41291
ES
623
624 switch (f->ilf_fields & XFS_ILOG_AFORK) {
625 case XFS_ILOG_AEXT:
626 printf(_("EXTENTS attr data\n"));
627 break;
628 case XFS_ILOG_ABROOT:
629 printf(_("BTREE attr data\n"));
630 break;
631 case XFS_ILOG_ADATA:
632 printf(_("LOCAL attr data\n"));
633 if (mode == S_IFDIR)
494434d7 634 xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size);
dda41291
ES
635 break;
636 default:
637 ASSERT((f->ilf_fields & XFS_ILOG_AFORK) == 0);
638 break;
a981f202 639 }
5e656dbb 640 *ptr += be32_to_cpu(op_head->oh_len);
0e22d318 641 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
04f1d806
HT
642 return skip_count;
643 skip_count--;
2bd0ea18 644 }
dda41291 645
04f1d806
HT
646 ASSERT(skip_count == 0);
647
2bd0ea18
NS
648 return 0;
649} /* xlog_print_trans_inode */
650
651
00ff2b10 652static int
d60ba955 653xlog_print_trans_dquot(char **ptr, int len, int *i, int num_ops)
c3cf3190
NS
654{
655 xfs_dq_logformat_t *f;
656 xfs_dq_logformat_t lbuf = {0};
657 xfs_disk_dquot_t ddq;
878c1b90 658 xlog_op_header_t *head = NULL;
c3cf3190
NS
659 int num, skip;
660
661 /*
662 * print dquot header region
663 *
dab9b8d6 664 * memmove to ensure 8-byte alignment for the long longs in
c3cf3190
NS
665 * xfs_dq_logformat_t structure
666 */
68d16907 667 memmove(&lbuf, *ptr, min(sizeof(xfs_dq_logformat_t), len));
c3cf3190
NS
668 f = &lbuf;
669 (*i)++; /* bump index */
670 *ptr += len;
dfc130f3 671
c3cf3190 672 if (len == sizeof(xfs_dq_logformat_t)) {
9ee7055c
AM
673 printf(_("#regs: %d id: 0x%x"), f->qlf_size, f->qlf_id);
674 printf(_(" blkno: %lld len: %d boff: %d\n"),
c3cf3190
NS
675 (long long)f->qlf_blkno, f->qlf_len, f->qlf_boffset);
676 } else {
677 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
9ee7055c 678 printf(_("DQUOT: #regs: %d Not printing rest of data\n"),
c3cf3190
NS
679 f->qlf_size);
680 return f->qlf_size;
681 }
682 num = f->qlf_size-1;
683
684 /* Check if all regions in this log item were in the given LR ptr */
685 if (*i+num > num_ops-1) {
686 skip = num - (num_ops-1-*i);
687 num = num_ops-1-*i;
688 } else {
689 skip = 0;
690 }
691
692 while (num-- > 0) {
693 head = (xlog_op_header_t *)*ptr;
694 xlog_print_op_header(head, *i, ptr);
5e656dbb 695 ASSERT(be32_to_cpu(head->oh_len) == sizeof(xfs_disk_dquot_t));
dab9b8d6 696 memmove(&ddq, *ptr, sizeof(xfs_disk_dquot_t));
9ee7055c 697 printf(_("DQUOT: magic 0x%hx flags 0%ho\n"),
5e656dbb
BN
698 be16_to_cpu(ddq.d_magic), ddq.d_flags);
699 *ptr += be32_to_cpu(head->oh_len);
c3cf3190
NS
700 }
701 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
702 skip++;
703 return skip;
704} /* xlog_print_trans_dquot */
705
2bd0ea18 706
2e6b5c91
DC
707STATIC int
708xlog_print_trans_icreate(
d60ba955 709 char **ptr,
2e6b5c91
DC
710 int len,
711 int *i,
712 int num_ops)
713{
714 struct xfs_icreate_log icl_buf = {0};
715 struct xfs_icreate_log *icl;
716
68d16907 717 memmove(&icl_buf, *ptr, min(sizeof(struct xfs_icreate_log), len));
2e6b5c91 718 icl = &icl_buf;
2e6b5c91
DC
719 *ptr += len;
720
721 /* handle complete header only */
722 if (len != sizeof(struct xfs_icreate_log)) {
723 printf(_("ICR: split header, not printing\n"));
724 return 1; /* to skip leftover in next region */
725 }
726
727 printf(_("ICR: #ag: %d agbno: 0x%x len: %d\n"
728 " cnt: %d isize: %d gen: 0x%x\n"),
729 be32_to_cpu(icl->icl_ag), be32_to_cpu(icl->icl_agbno),
730 be32_to_cpu(icl->icl_length), be32_to_cpu(icl->icl_count),
731 be32_to_cpu(icl->icl_isize), be32_to_cpu(icl->icl_gen));
732 return 0;
733}
734
2bd0ea18
NS
735/******************************************************************************
736 *
737 * Log print routines
738 *
739 ******************************************************************************
740 */
741
742void
999f0b9c 743xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence)
2bd0ea18
NS
744{
745#define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
746 xfs_off_t offset;
747
748 if (whence == SEEK_SET)
749 offset = BBTOOFF64(blkno+log->l_logBBstart);
750 else
751 offset = BBTOOFF64(blkno);
dc8878f4
FJ
752 if (lseek(fd, offset, whence) < 0) {
753 fprintf(stderr, _("%s: lseek to %lld failed: %s\n"),
e7134dda 754 progname, (long long)offset, strerror(errno));
2bd0ea18
NS
755 exit(1);
756 }
757} /* xlog_print_lseek */
758
759
00ff2b10 760static void
d60ba955 761print_lsn(char *string,
5e656dbb 762 __be64 *lsn)
2bd0ea18 763{
dfc130f3 764 printf("%s: %u,%u", string,
5e656dbb 765 CYCLE_LSN(be64_to_cpu(*lsn)), BLOCK_LSN(be64_to_cpu(*lsn)));
2bd0ea18
NS
766}
767
768
00ff2b10 769static int
494434d7
DC
770xlog_print_record(
771 struct xlog *log,
772 int fd,
773 int num_ops,
774 int len,
775 int *read_type,
d60ba955 776 char **partial_buf,
494434d7
DC
777 xlog_rec_header_t *rhead,
778 xlog_rec_ext_header_t *xhdrs,
779 int bad_hdr_warn)
2bd0ea18 780{
d60ba955 781 char *buf, *ptr;
a223e636 782 int read_len, skip, lost_context = 0;
dfb5b7da 783 int ret, n, i, j, k;
2bd0ea18
NS
784
785 if (print_no_print)
786 return NO_ERROR;
dfc130f3 787
2bd0ea18 788 if (!len) {
dfc130f3
RC
789 printf("\n");
790 return NO_ERROR;
2bd0ea18
NS
791 }
792
793 /* read_len must read up to some block boundary */
794 read_len = (int) BBTOB(BTOBB(len));
795
796 /* read_type => don't malloc() new buffer, use old one */
797 if (*read_type == FULL_READ) {
d60ba955 798 if ((ptr = buf = malloc(read_len)) == NULL) {
9ee7055c 799 fprintf(stderr, _("%s: xlog_print_record: malloc failed\n"), progname);
2bd0ea18
NS
800 exit(1);
801 }
802 } else {
803 read_len -= *read_type;
d60ba955 804 buf = (char *)((intptr_t)(*partial_buf) + (intptr_t)(*read_type));
2bd0ea18
NS
805 ptr = *partial_buf;
806 }
807 if ((ret = (int) read(fd, buf, read_len)) == -1) {
9ee7055c 808 fprintf(stderr, _("%s: xlog_print_record: read error\n"), progname);
2bd0ea18
NS
809 exit(1);
810 }
811 /* Did we overflow the end? */
812 if (*read_type == FULL_READ &&
5e656dbb 813 BLOCK_LSN(be64_to_cpu(rhead->h_lsn)) + BTOBB(read_len) >=
46eca962 814 logBBsize) {
5e656dbb 815 *read_type = BBTOB(logBBsize - BLOCK_LSN(be64_to_cpu(rhead->h_lsn))-1);
2bd0ea18
NS
816 *partial_buf = buf;
817 return PARTIAL_READ;
818 }
dfc130f3 819
2bd0ea18
NS
820 /* Did we read everything? */
821 if ((ret == 0 && read_len != 0) || ret != read_len) {
822 *read_type = ret;
823 *partial_buf = buf;
824 return PARTIAL_READ;
825 }
826 if (*read_type != FULL_READ)
827 read_len += *read_type;
dfc130f3 828
dfb5b7da 829 /* Everything read in. Start from beginning of buffer
830 * Unpack the data, by putting the saved cycle-data back
831 * into the first word of each BB.
832 * Do some checks.
46eca962 833 */
2bd0ea18
NS
834 buf = ptr;
835 for (i = 0; ptr < buf + read_len; ptr += BBSIZE, i++) {
dfb5b7da 836 xlog_rec_header_t *rechead = (xlog_rec_header_t *)ptr;
837
838 /* sanity checks */
5e656dbb 839 if (be32_to_cpu(rechead->h_magicno) == XLOG_HEADER_MAGIC_NUM) {
dfb5b7da 840 /* data should not have magicno as first word
841 * as it should by cycle#
842 */
2bd0ea18
NS
843 free(buf);
844 return -1;
845 } else {
dfb5b7da 846 /* verify cycle#
847 * FIXME: cycle+1 should be a macro pv#900369
848 */
5e656dbb
BN
849 if (be32_to_cpu(rhead->h_cycle) !=
850 be32_to_cpu(*(__be32 *)ptr)) {
04536bae
ES
851 if ((*read_type == FULL_READ) ||
852 (be32_to_cpu(rhead->h_cycle) + 1 !=
853 be32_to_cpu(*(__be32 *)ptr))) {
854 free(buf);
855 return -1;
856 }
2bd0ea18
NS
857 }
858 }
dfb5b7da 859
860 /* copy back the data from the header */
861 if (i < XLOG_HEADER_CYCLE_SIZE / BBSIZE) {
862 /* from 1st header */
5e656dbb 863 *(__be32 *)ptr = rhead->h_cycle_data[i];
dfb5b7da 864 }
865 else {
866 ASSERT(xhdrs != NULL);
867 /* from extra headers */
868 j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
dab9b8d6 869 k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
5e656dbb 870 *(__be32 *)ptr = xhdrs[j-1].xh_cycle_data[k];
dfb5b7da 871 }
dab9b8d6 872
2bd0ea18 873 }
dfb5b7da 874
2bd0ea18
NS
875 ptr = buf;
876 for (i=0; i<num_ops; i++) {
a8cfa1a4
ES
877 int continued;
878
dfb5b7da 879 xlog_op_header_t *op_head = (xlog_op_header_t *)ptr;
880
2bd0ea18 881 print_xlog_op_line();
2bd0ea18 882 xlog_print_op_header(op_head, i, &ptr);
0e22d318
ES
883 continued = ((op_head->oh_flags & XLOG_WAS_CONT_TRANS) ||
884 (op_head->oh_flags & XLOG_CONTINUE_TRANS));
2bd0ea18 885
8e78288a
DC
886 if (continued && be32_to_cpu(op_head->oh_len) == 0)
887 continue;
888
889 if (print_no_data) {
5e656dbb 890 for (n = 0; n < be32_to_cpu(op_head->oh_len); n++) {
8e78288a
DC
891 printf("0x%02x ", (unsigned int)*ptr);
892 if (n % 16 == 15)
893 printf("\n");
2bd0ea18
NS
894 ptr++;
895 }
896 printf("\n");
897 continue;
898 }
8e78288a
DC
899
900 /* print transaction data */
5e656dbb 901 if (xlog_print_find_tid(be32_to_cpu(op_head->oh_tid),
2bd0ea18 902 op_head->oh_flags & XLOG_WAS_CONT_TRANS)) {
9ee7055c 903 printf(_("Left over region from split log item\n"));
a223e636 904 /* Skip this leftover bit */
5e656dbb 905 ptr += be32_to_cpu(op_head->oh_len);
a223e636
ES
906 /* We've lost context; don't complain if next one looks bad too */
907 lost_context = 1;
2bd0ea18
NS
908 continue;
909 }
8e78288a 910
5e656dbb 911 if (be32_to_cpu(op_head->oh_len) != 0) {
2bd0ea18
NS
912 if (*(uint *)ptr == XFS_TRANS_HEADER_MAGIC) {
913 skip = xlog_print_trans_header(&ptr,
5e656dbb 914 be32_to_cpu(op_head->oh_len));
2bd0ea18
NS
915 } else {
916 switch (*(unsigned short *)ptr) {
2bd0ea18
NS
917 case XFS_LI_BUF: {
918 skip = xlog_print_trans_buffer(&ptr,
5e656dbb 919 be32_to_cpu(op_head->oh_len),
2bd0ea18
NS
920 &i, num_ops);
921 break;
922 }
2e6b5c91
DC
923 case XFS_LI_ICREATE: {
924 skip = xlog_print_trans_icreate(&ptr,
925 be32_to_cpu(op_head->oh_len),
926 &i, num_ops);
927 break;
928 }
2bd0ea18 929 case XFS_LI_INODE: {
494434d7 930 skip = xlog_print_trans_inode(log, &ptr,
5e656dbb 931 be32_to_cpu(op_head->oh_len),
a8cfa1a4 932 &i, num_ops, continued);
2bd0ea18
NS
933 break;
934 }
c3cf3190
NS
935 case XFS_LI_DQUOT: {
936 skip = xlog_print_trans_dquot(&ptr,
5e656dbb 937 be32_to_cpu(op_head->oh_len),
c3cf3190
NS
938 &i, num_ops);
939 break;
940 }
2bd0ea18
NS
941 case XFS_LI_EFI: {
942 skip = xlog_print_trans_efi(&ptr,
9404cb40
MT
943 be32_to_cpu(op_head->oh_len),
944 continued);
2bd0ea18
NS
945 break;
946 }
947 case XFS_LI_EFD: {
948 skip = xlog_print_trans_efd(&ptr,
5e656dbb 949 be32_to_cpu(op_head->oh_len));
2bd0ea18
NS
950 break;
951 }
4428538d
DW
952 case XFS_LI_RUI: {
953 skip = xlog_print_trans_rui(&ptr,
954 be32_to_cpu(op_head->oh_len),
955 continued);
956 break;
957 }
958 case XFS_LI_RUD: {
959 skip = xlog_print_trans_rud(&ptr,
960 be32_to_cpu(op_head->oh_len));
961 break;
962 }
77e3149e
DW
963 case XFS_LI_CUI: {
964 skip = xlog_print_trans_cui(&ptr,
965 be32_to_cpu(op_head->oh_len),
966 continued);
967 break;
968 }
969 case XFS_LI_CUD: {
970 skip = xlog_print_trans_cud(&ptr,
971 be32_to_cpu(op_head->oh_len));
972 break;
973 }
dc4957df
DW
974 case XFS_LI_BUI: {
975 skip = xlog_print_trans_bui(&ptr,
976 be32_to_cpu(op_head->oh_len),
977 continued);
978 break;
979 }
980 case XFS_LI_BUD: {
981 skip = xlog_print_trans_bud(&ptr,
982 be32_to_cpu(op_head->oh_len));
983 break;
984 }
c3cf3190
NS
985 case XFS_LI_QUOTAOFF: {
986 skip = xlog_print_trans_qoff(&ptr,
5e656dbb 987 be32_to_cpu(op_head->oh_len));
c3cf3190
NS
988 break;
989 }
2bd0ea18 990 case XLOG_UNMOUNT_TYPE: {
9ee7055c 991 printf(_("Unmount filesystem\n"));
2bd0ea18
NS
992 skip = 0;
993 break;
994 }
995 default: {
a223e636 996 if (bad_hdr_warn && !lost_context) {
20526770
DC
997 fprintf(stderr,
998 _("%s: unknown log operation type (%x)\n"),
999 progname, *(unsigned short *)ptr);
1000 if (print_exit) {
1001 free(buf);
1002 return BAD_HEADER;
1003 }
1004 } else {
1005 printf(
1006 _("Left over region from split log item\n"));
2c794e6e 1007 }
2bd0ea18 1008 skip = 0;
5e656dbb 1009 ptr += be32_to_cpu(op_head->oh_len);
a223e636 1010 lost_context = 0;
2bd0ea18
NS
1011 }
1012 } /* switch */
1013 } /* else */
1014 if (skip != 0)
5e656dbb 1015 xlog_print_add_to_trans(be32_to_cpu(op_head->oh_tid), skip);
2bd0ea18
NS
1016 }
1017 }
1018 printf("\n");
1019 free(buf);
1020 return NO_ERROR;
1021} /* xlog_print_record */
1022
1023
00ff2b10 1024static int
20526770 1025xlog_print_rec_head(xlog_rec_header_t *head, int *len, int bad_hdr_warn)
2bd0ea18
NS
1026{
1027 int i;
1028 char uub[64];
1029 int datalen,bbs;
dfc130f3 1030
2bd0ea18 1031 if (print_no_print)
5e656dbb 1032 return be32_to_cpu(head->h_num_logops);
dfc130f3 1033
46eca962 1034 if (!head->h_magicno)
dfc130f3 1035 return ZEROED_LOG;
2bd0ea18 1036
5e656dbb 1037 if (be32_to_cpu(head->h_magicno) != XLOG_HEADER_MAGIC_NUM) {
20526770
DC
1038 if (bad_hdr_warn)
1039 printf(_("Header 0x%x wanted 0x%x\n"),
1040 be32_to_cpu(head->h_magicno),
1041 XLOG_HEADER_MAGIC_NUM);
2bd0ea18
NS
1042 return BAD_HEADER;
1043 }
dfc130f3 1044
dfb5b7da 1045 /* check for cleared blocks written by xlog_clear_stale_blocks() */
a2ceac1f 1046 if (!head->h_len && !head->h_crc && !head->h_prev_block &&
46eca962 1047 !head->h_num_logops && !head->h_size)
dfb5b7da 1048 return CLEARED_BLKS;
1049
5e656dbb 1050 datalen=be32_to_cpu(head->h_len);
dfb5b7da 1051 bbs=BTOBB(datalen);
dfc130f3 1052
9ee7055c 1053 printf(_("cycle: %d version: %d "),
5e656dbb
BN
1054 be32_to_cpu(head->h_cycle),
1055 be32_to_cpu(head->h_version));
1056 print_lsn(" lsn", &head->h_lsn);
1057 print_lsn(" tail_lsn", &head->h_tail_lsn);
2bd0ea18 1058 printf("\n");
9ee7055c 1059 printf(_("length of Log Record: %d prev offset: %d num ops: %d\n"),
dfc130f3 1060 datalen,
5e656dbb
BN
1061 be32_to_cpu(head->h_prev_block),
1062 be32_to_cpu(head->h_num_logops));
dfc130f3 1063
2bd0ea18 1064 if (print_overwrite) {
9ee7055c 1065 printf(_("cycle num overwrites: "));
68d16907 1066 for (i=0; i< min(bbs, XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++)
2bd0ea18 1067 printf("%d - 0x%x ",
dfc130f3 1068 i,
5e656dbb 1069 be32_to_cpu(head->h_cycle_data[i]));
dfc130f3 1070 printf("\n");
2bd0ea18 1071 }
dfc130f3 1072
4d32d744 1073 platform_uuid_unparse(&head->h_fs_uuid, uub);
9ee7055c 1074 printf(_("uuid: %s format: "), uub);
5e656dbb 1075 switch (be32_to_cpu(head->h_fmt)) {
dfc130f3 1076 case XLOG_FMT_UNKNOWN:
9ee7055c 1077 printf(_("unknown\n"));
dfc130f3
RC
1078 break;
1079 case XLOG_FMT_LINUX_LE:
9ee7055c 1080 printf(_("little endian linux\n"));
dfc130f3
RC
1081 break;
1082 case XLOG_FMT_LINUX_BE:
9ee7055c 1083 printf(_("big endian linux\n"));
dfc130f3
RC
1084 break;
1085 case XLOG_FMT_IRIX_BE:
9ee7055c 1086 printf(_("big endian irix\n"));
dfc130f3
RC
1087 break;
1088 default:
5e656dbb 1089 printf("? (%d)\n", be32_to_cpu(head->h_fmt));
dfc130f3 1090 break;
2bd0ea18 1091 }
9ee7055c 1092 printf(_("h_size: %d\n"), be32_to_cpu(head->h_size));
dab9b8d6 1093
5e656dbb
BN
1094 *len = be32_to_cpu(head->h_len);
1095 return(be32_to_cpu(head->h_num_logops));
2bd0ea18
NS
1096} /* xlog_print_rec_head */
1097
00ff2b10 1098static void
dfb5b7da 1099xlog_print_rec_xhead(xlog_rec_ext_header_t *head, int coverage)
1100{
1101 int i;
1102
1103 print_xlog_xhdr_line();
9ee7055c 1104 printf(_("extended-header: cycle: %d\n"), be32_to_cpu(head->xh_cycle));
dfb5b7da 1105
1106 if (print_overwrite) {
9ee7055c 1107 printf(_("cycle num overwrites: "));
dfb5b7da 1108 for (i = 0; i < coverage; i++)
1109 printf("%d - 0x%x ",
1110 i,
5e656dbb 1111 be32_to_cpu(head->xh_cycle_data[i]));
dfb5b7da 1112 printf("\n");
1113 }
1114} /* xlog_print_rec_xhead */
1115
2bd0ea18
NS
1116static void
1117print_xlog_bad_zeroed(xfs_daddr_t blkno)
1118{
dfc130f3 1119 print_stars();
9ee7055c 1120 printf(_("* ERROR: found data after zeroed blocks block=%-21lld *\n"),
dfc130f3
RC
1121 (long long)blkno);
1122 print_stars();
2bd0ea18
NS
1123 if (print_exit)
1124 xlog_exit("Bad log - data after zeroed blocks");
1125} /* print_xlog_bad_zeroed */
1126
1127static void
d60ba955 1128print_xlog_bad_header(xfs_daddr_t blkno, char *buf)
2bd0ea18 1129{
dfc130f3 1130 print_stars();
9ee7055c 1131 printf(_("* ERROR: header cycle=%-11d block=%-21lld *\n"),
5e656dbb 1132 xlog_get_cycle(buf), (long long)blkno);
dfc130f3 1133 print_stars();
2bd0ea18
NS
1134 if (print_exit)
1135 xlog_exit("Bad log record header");
1136} /* print_xlog_bad_header */
1137
00ff2b10 1138static void
2bd0ea18
NS
1139print_xlog_bad_data(xfs_daddr_t blkno)
1140{
dfc130f3 1141 print_stars();
9ee7055c 1142 printf(_("* ERROR: data block=%-21lld *\n"),
dfc130f3
RC
1143 (long long)blkno);
1144 print_stars();
2bd0ea18
NS
1145 if (print_exit)
1146 xlog_exit("Bad data in log");
1147} /* print_xlog_bad_data */
1148
dfb5b7da 1149static void
1150print_xlog_bad_reqd_hdrs(xfs_daddr_t blkno, int num_reqd, int num_hdrs)
1151{
1152 print_stars();
9ee7055c 1153 printf(_("* ERROR: for header block=%lld\n"
dfb5b7da 1154 "* not enough hdrs for data length, "
9ee7055c 1155 "required num = %d, hdr num = %d\n"),
dfb5b7da 1156 (long long)blkno, num_reqd, num_hdrs);
1157 print_stars();
1158 if (print_exit)
9ee7055c 1159 xlog_exit(_("Not enough headers for data length."));
dfb5b7da 1160} /* print_xlog_bad_reqd_hdrs */
1161
1162static void
1163xlog_reallocate_xhdrs(int num_hdrs, xlog_rec_ext_header_t **ret_xhdrs)
1164{
1165 int len = (num_hdrs-1) * sizeof(xlog_rec_ext_header_t);
1166
1167 *ret_xhdrs = (xlog_rec_ext_header_t *)realloc(*ret_xhdrs, len);
1168 if (*ret_xhdrs == NULL) {
9ee7055c 1169 fprintf(stderr, _("%s: xlog_print: malloc failed for ext hdrs\n"), progname);
dfb5b7da 1170 exit(1);
1171 }
1172}
1173
1174/* for V2 logs read each extra hdr and print it out */
dab9b8d6 1175static int
dfb5b7da 1176xlog_print_extended_headers(
1177 int fd,
1178 int len,
1179 xfs_daddr_t *blkno,
1180 xlog_rec_header_t *hdr,
1181 int *ret_num_hdrs,
1182 xlog_rec_ext_header_t **ret_xhdrs)
1183{
1184 int i, j;
1185 int coverage_bb;
1186 int num_hdrs;
1187 int num_required;
1188 char xhbuf[XLOG_HEADER_SIZE];
4add9d50 1189 xlog_rec_ext_header_t *xhdr;
dfb5b7da 1190
dab9b8d6 1191 num_required = howmany(len, XLOG_HEADER_CYCLE_SIZE);
5e656dbb 1192 num_hdrs = be32_to_cpu(hdr->h_size) / XLOG_HEADER_CYCLE_SIZE;
011207f6
BF
1193 if (be32_to_cpu(hdr->h_size) % XLOG_HEADER_CYCLE_SIZE)
1194 num_hdrs++;
dfb5b7da 1195
1196 if (num_required > num_hdrs) {
1197 print_xlog_bad_reqd_hdrs((*blkno)-1, num_required, num_hdrs);
1198 }
1199
1200 if (num_hdrs == 1) {
1201 free(*ret_xhdrs);
1202 *ret_xhdrs = NULL;
1203 *ret_num_hdrs = 1;
1204 return 0;
1205 }
1206
1207 if (*ret_xhdrs == NULL || num_hdrs > *ret_num_hdrs) {
1208 xlog_reallocate_xhdrs(num_hdrs, ret_xhdrs);
1209 }
1210
1211 *ret_num_hdrs = num_hdrs;
1212
1213 /* don't include 1st header */
4add9d50 1214 for (i = 1, xhdr = *ret_xhdrs; i < num_hdrs; i++, (*blkno)++, xhdr++) {
dfb5b7da 1215 /* read one extra header blk */
1216 if (read(fd, xhbuf, 512) == 0) {
9ee7055c 1217 printf(_("%s: physical end of log\n"), progname);
dfb5b7da 1218 print_xlog_record_line();
1219 /* reached the end so return 1 */
1220 return 1;
1221 }
1222 if (print_only_data) {
9ee7055c 1223 printf(_("BLKNO: %lld\n"), (long long)*blkno);
dfb5b7da 1224 xlog_recover_print_data(xhbuf, 512);
1225 }
1226 else {
1227 if (i == num_hdrs - 1) {
dab9b8d6
BN
1228 /* last header */
1229 coverage_bb = BTOBB(len) %
1230 (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
dfb5b7da 1231 }
1232 else {
1233 /* earliear header */
1234 coverage_bb = XLOG_HEADER_CYCLE_SIZE / BBSIZE;
1235 }
1236 xlog_print_rec_xhead((xlog_rec_ext_header_t*)xhbuf, coverage_bb);
1237 }
1238
1239 /* Copy from buffer into xhdrs array for later.
1240 * Could endian convert here but then code later on
1241 * will look asymmetric with the 1 hdr normal case
1242 * which does endian coversion on access.
1243 */
4add9d50 1244 xhdr->xh_cycle = ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle;
dfb5b7da 1245 for (j = 0; j < XLOG_HEADER_CYCLE_SIZE / BBSIZE; j++) {
4add9d50 1246 xhdr->xh_cycle_data[j] =
dab9b8d6 1247 ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle_data[j];
dfb5b7da 1248 }
1249 }
1250 return 0;
1251}
1252
2bd0ea18
NS
1253
1254/*
1255 * This code is gross and needs to be rewritten.
1256 */
999f0b9c 1257void xfs_log_print(struct xlog *log,
dfc130f3 1258 int fd,
2bd0ea18
NS
1259 int print_block_start)
1260{
dfb5b7da 1261 char hbuf[XLOG_HEADER_SIZE];
1262 xlog_rec_header_t *hdr = (xlog_rec_header_t *)&hbuf[0];
1263 xlog_rec_ext_header_t *xhdrs = NULL;
1264 int num_ops, len, num_hdrs = 1;
1265 xfs_daddr_t block_end = 0, block_start, blkno, error;
1266 xfs_daddr_t zeroed_blkno = 0, cleared_blkno = 0;
1267 int read_type = FULL_READ;
d60ba955 1268 char *partial_buf;
20526770
DC
1269 int zeroed = 0;
1270 int cleared = 0;
1271 int first_hdr_found = 0;
dab9b8d6 1272
2bd0ea18 1273 logBBsize = log->l_logBBsize;
dfc130f3 1274
2bd0ea18
NS
1275 /*
1276 * Normally, block_start and block_end are the same value since we
1277 * are printing the entire log. However, if the start block is given,
1278 * we still end at the end of the logical log.
1279 */
27527004 1280 if ((error = xlog_print_find_oldest(log, &block_end))) {
9ee7055c 1281 fprintf(stderr, _("%s: problem finding oldest LR\n"), progname);
dfb5b7da 1282 return;
2bd0ea18
NS
1283 }
1284 if (print_block_start == -1)
dfb5b7da 1285 block_start = block_end;
2bd0ea18 1286 else
dfb5b7da 1287 block_start = print_block_start;
2bd0ea18 1288 xlog_print_lseek(log, fd, block_start, SEEK_SET);
dfb5b7da 1289 blkno = block_start;
dfc130f3 1290
2bd0ea18
NS
1291 for (;;) {
1292 if (read(fd, hbuf, 512) == 0) {
9ee7055c 1293 printf(_("%s: physical end of log\n"), progname);
2bd0ea18
NS
1294 print_xlog_record_line();
1295 break;
dfc130f3 1296 }
2bd0ea18 1297 if (print_only_data) {
9ee7055c 1298 printf(_("BLKNO: %lld\n"), (long long)blkno);
dfb5b7da 1299 xlog_recover_print_data(hbuf, 512);
1300 blkno++;
1301 goto loop;
2bd0ea18 1302 }
20526770 1303 num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found);
2bd0ea18 1304 blkno++;
dfc130f3
RC
1305
1306 if (zeroed && num_ops != ZEROED_LOG) {
9ee7055c 1307 printf(_("%s: after %d zeroed blocks\n"), progname, zeroed);
dfc130f3
RC
1308 /* once we find zeroed blocks - that's all we expect */
1309 print_xlog_bad_zeroed(blkno-1);
1310 /* reset count since we're assuming previous zeroed blocks
1311 * were bad
1312 */
1313 zeroed = 0;
1314 }
1315
dab9b8d6 1316 if (num_ops == ZEROED_LOG ||
dfb5b7da 1317 num_ops == CLEARED_BLKS ||
1318 num_ops == BAD_HEADER) {
dfc130f3 1319 if (num_ops == ZEROED_LOG) {
dfb5b7da 1320 if (zeroed == 0)
1321 zeroed_blkno = blkno-1;
dfc130f3 1322 zeroed++;
dfb5b7da 1323 }
1324 else if (num_ops == CLEARED_BLKS) {
1325 if (cleared == 0)
1326 cleared_blkno = blkno-1;
1327 cleared++;
dfc130f3 1328 } else {
20526770
DC
1329 if (!first_hdr_found)
1330 block_start = blkno;
1331 else
1332 print_xlog_bad_header(blkno-1, hbuf);
dfc130f3
RC
1333 }
1334
2bd0ea18
NS
1335 goto loop;
1336 }
dfc130f3 1337
5e656dbb 1338 if (be32_to_cpu(hdr->h_version) == 2) {
dfb5b7da 1339 if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0)
1340 break;
1341 }
1342
494434d7 1343 error = xlog_print_record(log, fd, num_ops, len, &read_type, &partial_buf,
20526770
DC
1344 hdr, xhdrs, first_hdr_found);
1345 first_hdr_found++;
2bd0ea18
NS
1346 switch (error) {
1347 case 0: {
1348 blkno += BTOBB(len);
1349 if (print_block_start != -1 &&
1350 blkno >= block_end) /* If start specified, we */
1351 goto end; /* end early */
1352 break;
1353 }
1354 case -1: {
1355 print_xlog_bad_data(blkno-1);
1356 if (print_block_start != -1 &&
1357 blkno >= block_end) /* If start specified, */
1358 goto end; /* we end early */
1359 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1360 goto loop;
1361 }
1362 case PARTIAL_READ: {
dfc130f3 1363 print_xlog_record_line();
9ee7055c 1364 printf(_("%s: physical end of log\n"), progname);
dfc130f3 1365 print_xlog_record_line();
2bd0ea18
NS
1366 blkno = 0;
1367 xlog_print_lseek(log, fd, 0, SEEK_SET);
1368 /*
1369 * We may have hit the end of the log when we started at 0.
1370 * In this case, just end.
1371 */
1372 if (block_start == 0)
1373 goto end;
1374 goto partial_log_read;
1375 }
9ee7055c 1376 default: xlog_panic(_("illegal value"));
2bd0ea18
NS
1377 }
1378 print_xlog_record_line();
1379loop:
1380 if (blkno >= logBBsize) {
dfb5b7da 1381 if (cleared) {
9ee7055c 1382 printf(_("%s: skipped %d cleared blocks in range: %lld - %lld\n"),
83735711
NS
1383 progname, cleared,
1384 (long long)(cleared_blkno),
1385 (long long)(cleared + cleared_blkno - 1));
dfb5b7da 1386 if (cleared == logBBsize)
9ee7055c 1387 printf(_("%s: totally cleared log\n"), progname);
dfc130f3 1388
dfb5b7da 1389 cleared=0;
1390 }
1391 if (zeroed) {
9ee7055c 1392 printf(_("%s: skipped %d zeroed blocks in range: %lld - %lld\n"),
83735711
NS
1393 progname, zeroed,
1394 (long long)(zeroed_blkno),
1395 (long long)(zeroed + zeroed_blkno - 1));
dfb5b7da 1396 if (zeroed == logBBsize)
9ee7055c 1397 printf(_("%s: totally zeroed log\n"), progname);
dfb5b7da 1398
1399 zeroed=0;
1400 }
9ee7055c 1401 printf(_("%s: physical end of log\n"), progname);
dfb5b7da 1402 print_xlog_record_line();
1403 break;
2bd0ea18
NS
1404 }
1405 }
1406
1407 /* Do we need to print the first part of physical log? */
1408 if (block_start != 0) {
1409 blkno = 0;
1410 xlog_print_lseek(log, fd, 0, SEEK_SET);
1411 for (;;) {
1412 if (read(fd, hbuf, 512) == 0) {
9ee7055c 1413 xlog_panic(_("xlog_find_head: bad read"));
2bd0ea18
NS
1414 }
1415 if (print_only_data) {
9ee7055c 1416 printf(_("BLKNO: %lld\n"), (long long)blkno);
2bd0ea18
NS
1417 xlog_recover_print_data(hbuf, 512);
1418 blkno++;
1419 goto loop2;
1420 }
20526770 1421 num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found);
2bd0ea18 1422 blkno++;
dfc130f3 1423
dfb5b7da 1424 if (num_ops == ZEROED_LOG ||
1425 num_ops == CLEARED_BLKS ||
1426 num_ops == BAD_HEADER) {
1427 /* we only expect zeroed log entries or cleared log
dab9b8d6 1428 * entries at the end of the _physical_ log,
dfb5b7da 1429 * so treat them the same as bad blocks here
dfc130f3 1430 */
2bd0ea18 1431 print_xlog_bad_header(blkno-1, hbuf);
dfc130f3 1432
2bd0ea18
NS
1433 if (blkno >= block_end)
1434 break;
1435 continue;
1436 }
dfb5b7da 1437
5e656dbb 1438 if (be32_to_cpu(hdr->h_version) == 2) {
dfb5b7da 1439 if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0)
1440 break;
1441 }
1442
2bd0ea18 1443partial_log_read:
494434d7
DC
1444 error= xlog_print_record(log, fd, num_ops, len, &read_type,
1445 &partial_buf, (xlog_rec_header_t *)hbuf,
1446 xhdrs, first_hdr_found);
2bd0ea18
NS
1447 if (read_type != FULL_READ)
1448 len -= read_type;
1449 read_type = FULL_READ;
1450 if (!error)
1451 blkno += BTOBB(len);
1452 else {
1453 print_xlog_bad_data(blkno-1);
1454 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1455 goto loop2;
1456 }
1457 print_xlog_record_line();
1458loop2:
1459 if (blkno >= block_end)
1460 break;
dfc130f3 1461 }
2bd0ea18 1462 }
dfc130f3 1463
2bd0ea18 1464end:
9ee7055c 1465 printf(_("%s: logical end of log\n"), progname);
2bd0ea18
NS
1466 print_xlog_record_line();
1467}
299173ff
TS
1468
1469/*
87daa553
DC
1470 * if necessary, convert an xfs_inode_log_format struct from the old 32bit version
1471 * (which can have different field alignments) to the native 64 bit version
299173ff 1472 */
e784bcd5
DW
1473struct xfs_inode_log_format *
1474xfs_inode_item_format_convert(char *src_buf, uint len, struct xfs_inode_log_format *in_f)
299173ff 1475{
87daa553
DC
1476 struct xfs_inode_log_format_32 *in_f32;
1477
299173ff 1478 /* if we have native format then just return buf without copying data */
e784bcd5
DW
1479 if (len == sizeof(struct xfs_inode_log_format)) {
1480 return (struct xfs_inode_log_format *)src_buf;
299173ff
TS
1481 }
1482
87daa553
DC
1483 in_f32 = (struct xfs_inode_log_format_32 *)src_buf;
1484 in_f->ilf_type = in_f32->ilf_type;
1485 in_f->ilf_size = in_f32->ilf_size;
1486 in_f->ilf_fields = in_f32->ilf_fields;
1487 in_f->ilf_asize = in_f32->ilf_asize;
1488 in_f->ilf_dsize = in_f32->ilf_dsize;
1489 in_f->ilf_ino = in_f32->ilf_ino;
1490 /* copy biggest field of ilf_u */
95817f59
CH
1491 memcpy(&in_f->ilf_u.__pad, &in_f32->ilf_u.__pad,
1492 sizeof(in_f->ilf_u.__pad));
87daa553
DC
1493 in_f->ilf_blkno = in_f32->ilf_blkno;
1494 in_f->ilf_len = in_f32->ilf_len;
1495 in_f->ilf_boffset = in_f32->ilf_boffset;
1496
299173ff
TS
1497 return in_f;
1498}