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