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