2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
35 #define ZEROED_LOG (-4)
36 #define FULL_READ (-3)
37 #define PARTIAL_READ (-2)
38 #define BAD_HEADER (-1)
42 char *trans_type
[] = {
86 typedef struct xlog_split_item
{
87 struct xlog_split_item
*si_next
;
88 struct xlog_split_item
*si_prev
;
93 xlog_split_item_t
*split_list
= 0;
96 print_xlog_op_line(void)
98 printf("--------------------------------------"
99 "--------------------------------------\n");
100 } /* print_xlog_op_line */
103 print_xlog_record_line(void)
105 printf("======================================"
106 "======================================\n");
107 } /* print_xlog_record_line */
112 printf("***********************************"
113 "***********************************\n");
114 } /* print_xlog_record_line */
117 * Given a pointer to a data segment, print out the data as if it were
118 * a log operation header.
121 xlog_print_op_header(xlog_op_header_t
*op_head
,
125 xlog_op_header_t hbuf
;
128 * bcopy because on 64/n32, partial reads can cause the op_head
129 * pointer to come in pointing to an odd-numbered byte
131 bcopy(op_head
, &hbuf
, sizeof(xlog_op_header_t
));
133 *ptr
+= sizeof(xlog_op_header_t
);
134 printf("Oper (%d): tid: %x len: %d clientid: %s ", i
,
135 INT_GET(op_head
->oh_tid
, ARCH_CONVERT
),
136 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
137 (op_head
->oh_clientid
== XFS_TRANSACTION
? "TRANS" :
138 (op_head
->oh_clientid
== XFS_LOG
? "LOG" : "ERROR")));
140 if (op_head
->oh_flags
) {
141 if (op_head
->oh_flags
& XLOG_START_TRANS
)
143 if (op_head
->oh_flags
& XLOG_COMMIT_TRANS
)
145 if (op_head
->oh_flags
& XLOG_WAS_CONT_TRANS
)
147 if (op_head
->oh_flags
& XLOG_UNMOUNT_TRANS
)
149 if (op_head
->oh_flags
& XLOG_CONTINUE_TRANS
)
151 if (op_head
->oh_flags
& XLOG_END_TRANS
)
157 } /* xlog_print_op_header */
161 xlog_print_add_to_trans(xlog_tid_t tid
,
164 xlog_split_item_t
*item
;
166 item
= (xlog_split_item_t
*)calloc(sizeof(xlog_split_item_t
), 1);
168 item
->si_skip
= skip
;
169 item
->si_next
= split_list
;
172 split_list
->si_prev
= item
;
174 } /* xlog_print_add_to_trans */
178 xlog_print_find_tid(xlog_tid_t tid
, uint was_cont
)
180 xlog_split_item_t
*listp
= split_list
;
183 if (was_cont
!= 0) /* Not first time we have used this tid */
189 if (listp
->si_tid
== tid
)
191 listp
= listp
->si_next
;
196 if (--listp
->si_skip
== 0) {
197 if (listp
== split_list
) { /* delete at head */
198 split_list
= listp
->si_next
;
200 split_list
->si_prev
= NULL
;
203 listp
->si_next
->si_prev
= listp
->si_prev
;
204 listp
->si_prev
->si_next
= listp
->si_next
;
209 } /* xlog_print_find_tid */
212 xlog_print_trans_header(xfs_caddr_t
*ptr
, int len
)
214 xfs_trans_header_t
*h
;
215 xfs_caddr_t cptr
= *ptr
;
217 char *magic_c
= (char *)&magic
;
221 magic
=*(__uint32_t
*)cptr
; /* XXX INT_GET soon */
225 #if __BYTE_ORDER == __LITTLE_ENDIAN
226 magic_c
[3], magic_c
[2], magic_c
[1], magic_c
[0]);
228 magic_c
[0], magic_c
[1], magic_c
[2], magic_c
[3]);
230 if (len
!= sizeof(xfs_trans_header_t
)) {
231 printf(" Not enough data to decode further\n");
234 h
= (xfs_trans_header_t
*)cptr
;
235 printf(" type: %s tid: %x num_items: %d\n",
236 trans_type
[h
->th_type
], h
->th_tid
, h
->th_num_items
);
238 } /* xlog_print_trans_header */
242 xlog_print_trans_buffer(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
244 xfs_buf_log_format_t
*f
;
245 xfs_buf_log_format_v1_t
*old_f
;
248 xfs_disk_dquot_t
*dq
;
249 xlog_op_header_t
*head
= 0;
252 int bucket
, col
, buckets
;
254 xfs_buf_log_format_t lbuf
;
255 int size
, blen
, map_size
, struct_size
;
259 * bcopy to ensure 8-byte alignment for the long longs in
260 * buf_log_format_t structure
262 bcopy(*ptr
, &lbuf
, sizeof(xfs_buf_log_format_t
));
266 if (f
->blf_type
== XFS_LI_BUF
) {
267 blkno
= f
->blf_blkno
;
270 map_size
= f
->blf_map_size
;
271 struct_size
= sizeof(xfs_buf_log_format_t
);
273 old_f
= (xfs_buf_log_format_v1_t
*)f
;
274 blkno
= old_f
->blf_blkno
;
275 size
= old_f
->blf_size
;
276 blen
= old_f
->blf_len
;
277 map_size
= old_f
->blf_map_size
;
278 struct_size
= sizeof(xfs_buf_log_format_v1_t
);
280 switch (f
->blf_type
) {
291 printf("DQUOT BUF: ");
294 printf("UNKNOWN BUF: ");
297 if (len
>= struct_size
) {
298 ASSERT((len
- sizeof(struct_size
)) % sizeof(int) == 0);
299 printf("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d\n",
300 size
, (long long)blkno
, (unsigned long long)blkno
, blen
, map_size
);
304 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
305 printf("#regs: %d Not printing rest of data\n", f
->blf_size
);
310 /* Check if all regions in this log item were in the given LR ptr */
311 if (*i
+num
> num_ops
-1) {
312 skip
= num
- (num_ops
-1-*i
);
319 head
= (xlog_op_header_t
*)*ptr
;
320 xlog_print_op_header(head
, *i
, ptr
);
322 printf("SUPER BLOCK Buffer: ");
323 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) < 4*8) {
324 printf("Out of space\n");
328 * bcopy because *ptr may not be 8-byte aligned
330 bcopy(*ptr
, &x
, sizeof(long long));
331 bcopy(*ptr
+8, &y
, sizeof(long long));
332 printf("icount: %lld ifree: %lld ",
333 INT_GET(x
, ARCH_CONVERT
),
334 INT_GET(y
, ARCH_CONVERT
));
335 bcopy(*ptr
+16, &x
, sizeof(long long));
336 bcopy(*ptr
+24, &y
, sizeof(long long));
337 printf("fdblks: %lld frext: %lld\n",
338 INT_GET(x
, ARCH_CONVERT
),
339 INT_GET(y
, ARCH_CONVERT
));
342 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_AGI_MAGIC
) {
343 agi
= (xfs_agi_t
*)(*ptr
);
344 printf("AGI Buffer: XAGI ");
345 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) <
347 XFS_AGI_UNLINKED_BUCKETS
*sizeof(xfs_agino_t
)) {
348 printf("out of space\n");
352 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
));
353 printf("seq#: %d len: %d cnt: %d root: %d\n",
354 INT_GET(agi
->agi_seqno
, ARCH_CONVERT
),
355 INT_GET(agi
->agi_length
, ARCH_CONVERT
),
356 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
357 INT_GET(agi
->agi_root
, ARCH_CONVERT
));
358 printf("level: %d free#: 0x%x newino: 0x%x\n",
359 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
360 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
361 INT_GET(agi
->agi_newino
, ARCH_CONVERT
));
362 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) == 128) {
364 } else if (INT_GET(head
->oh_len
, ARCH_CONVERT
) == 256) {
367 buckets
= XFS_AGI_UNLINKED_BUCKETS
;
369 for (bucket
= 0; bucket
< buckets
;) {
370 printf("bucket[%d - %d]: ", bucket
, bucket
+3);
371 for (col
= 0; col
< 4; col
++, bucket
++) {
372 if (bucket
< buckets
) {
374 INT_GET(agi
->agi_unlinked
[bucket
], ARCH_CONVERT
));
380 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_AGF_MAGIC
) {
381 agf
= (xfs_agf_t
*)(*ptr
);
382 printf("AGF Buffer: XAGF ");
383 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) < sizeof(xfs_agf_t
)) {
384 printf("Out of space\n");
387 printf("ver: %d seq#: %d len: %d \n",
388 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
),
389 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
390 INT_GET(agf
->agf_length
, ARCH_CONVERT
));
391 printf("root BNO: %d CNT: %d\n",
392 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNOi
],
394 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNTi
],
396 printf("level BNO: %d CNT: %d\n",
397 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNOi
],
399 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNTi
],
401 printf("1st: %d last: %d cnt: %d "
402 "freeblks: %d longest: %d\n",
403 INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
),
404 INT_GET(agf
->agf_fllast
, ARCH_CONVERT
),
405 INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
406 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
407 INT_GET(agf
->agf_longest
, ARCH_CONVERT
));
409 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_DQUOT_MAGIC
) {
410 dq
= (xfs_disk_dquot_t
*)(*ptr
);
411 printf("DQUOT Buffer: DQ ");
412 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) <
413 sizeof(xfs_disk_dquot_t
)) {
414 printf("Out of space\n");
418 printf("ver: %d flags: 0x%x id: %d \n",
419 INT_GET(dq
->d_version
, ARCH_CONVERT
),
420 INT_GET(dq
->d_flags
, ARCH_CONVERT
),
421 INT_GET(dq
->d_id
, ARCH_CONVERT
));
422 printf("blk limits hard: %llu soft: %llu\n",
424 INT_GET(dq
->d_blk_hardlimit
, ARCH_CONVERT
),
426 INT_GET(dq
->d_blk_softlimit
, ARCH_CONVERT
));
427 printf("blk count: %llu warns: %d timer: %d\n",
429 INT_GET(dq
->d_bcount
, ARCH_CONVERT
),
430 INT_GET(dq
->d_bwarns
, ARCH_CONVERT
),
431 INT_GET(dq
->d_btimer
, ARCH_CONVERT
));
432 printf("ino limits hard: %llu soft: %llu\n",
434 INT_GET(dq
->d_ino_hardlimit
, ARCH_CONVERT
),
436 INT_GET(dq
->d_ino_softlimit
, ARCH_CONVERT
));
437 printf("ino count: %llu warns: %d timer: %d\n",
439 INT_GET(dq
->d_icount
, ARCH_CONVERT
),
440 INT_GET(dq
->d_iwarns
, ARCH_CONVERT
),
441 INT_GET(dq
->d_itimer
, ARCH_CONVERT
));
444 printf("BUF DATA\n");
446 uint
*dp
= (uint
*)*ptr
;
447 int nums
= INT_GET(head
->oh_len
, ARCH_CONVERT
) >> 2;
462 *ptr
+= INT_GET(head
->oh_len
, ARCH_CONVERT
);
464 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
467 } /* xlog_print_trans_buffer */
471 xlog_print_trans_efd(xfs_caddr_t
*ptr
, uint len
)
473 xfs_efd_log_format_t
*f
;
476 xfs_efd_log_format_t lbuf
;
479 * bcopy to ensure 8-byte alignment for the long longs in
480 * xfs_efd_log_format_t structure
482 bcopy(*ptr
, &lbuf
, sizeof(xfs_efd_log_format_t
));
485 if (len
>= sizeof(xfs_efd_log_format_t
)) {
486 printf("EFD: #regs: %d num_extents: %d id: 0x%llx\n",
487 f
->efd_size
, f
->efd_nextents
, (unsigned long long)f
->efd_efi_id
);
489 for (i
=0; i
< f
->efd_size
; i
++) {
490 printf("(s: 0x%llx, l: %d) ",
491 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
492 if (i
% 4 == 3) printf("\n");
495 if (i
% 4 != 0) printf("\n");
498 printf("EFD: Not enough data to decode further\n");
501 } /* xlog_print_trans_efd */
505 xlog_print_trans_efi(xfs_caddr_t
*ptr
, uint len
)
507 xfs_efi_log_format_t
*f
;
510 xfs_efi_log_format_t lbuf
;
513 * bcopy to ensure 8-byte alignment for the long longs in
514 * xfs_efi_log_format_t structure
516 bcopy(*ptr
, &lbuf
, sizeof(xfs_efi_log_format_t
));
519 if (len
>= sizeof(xfs_efi_log_format_t
)) {
520 printf("EFI: #regs: %d num_extents: %d id: 0x%llx\n",
521 f
->efi_size
, f
->efi_nextents
, (unsigned long long)f
->efi_id
);
523 for (i
=0; i
< f
->efi_size
; i
++) {
524 printf("(s: 0x%llx, l: %d) ",
525 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
526 if (i
% 4 == 3) printf("\n");
529 if (i
% 4 != 0) printf("\n");
532 printf("EFI: Not enough data to decode further\n");
535 } /* xlog_print_trans_efi */
540 xlog_print_trans_inode_core(xfs_dinode_core_t
*ip
)
542 printf("INODE CORE\n");
543 printf("magic 0x%hx mode 0%ho version %d format %d\n",
544 ip
->di_magic
, ip
->di_mode
, (int)ip
->di_version
,
546 printf("nlink %hd uid %d gid %d\n",
547 ip
->di_nlink
, ip
->di_uid
, ip
->di_gid
);
548 printf("atime 0x%x mtime 0x%x ctime 0x%x\n",
549 ip
->di_atime
.t_sec
, ip
->di_mtime
.t_sec
, ip
->di_ctime
.t_sec
);
550 printf("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n",
551 (unsigned long long)ip
->di_size
, (unsigned long long)ip
->di_nblocks
,
552 ip
->di_extsize
, ip
->di_nextents
);
553 printf("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n",
554 ip
->di_anextents
, (int)ip
->di_forkoff
, ip
->di_dmevmask
,
556 printf("flags 0x%x gen 0x%x\n",
557 ip
->di_flags
, ip
->di_gen
);
561 xlog_print_dir_sf(xfs_dir_shortform_t
*sfp
, int size
)
567 xfs_dir_sf_entry_t
*sfep
;
569 /* XXX need to determine whether this is v1 or v2, then
570 print appropriate structure */
572 printf("SHORTFORM DIRECTORY size %d\n",
574 /* bail out for now */
578 printf("SHORTFORM DIRECTORY size %d count %d\n",
579 size
, sfp
->hdr
.count
);
580 bcopy(&(sfp
->hdr
.parent
), &ino
, sizeof(ino
));
581 printf(".. ino 0x%llx\n", (unsigned long long)INT_GET(ino
, ARCH_CONVERT
));
583 count
= (uint
)(sfp
->hdr
.count
);
584 sfep
= &(sfp
->list
[0]);
585 for (i
= 0; i
< count
; i
++) {
586 bcopy(&(sfep
->inumber
), &ino
, sizeof(ino
));
587 bcopy((sfep
->name
), namebuf
, sfep
->namelen
);
588 namebuf
[sfep
->namelen
] = '\0';
589 printf("%s ino 0x%llx namelen %d\n",
590 namebuf
, (unsigned long long)ino
, sfep
->namelen
);
591 sfep
= XFS_DIR_SF_NEXTENTRY(sfep
);
596 xlog_print_trans_inode(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
598 xfs_inode_log_format_t
*f
;
599 xfs_inode_log_format_t_v1
*old_f
;
600 xfs_dinode_core_t dino
;
601 xlog_op_header_t
*op_head
;
603 xfs_inode_log_format_t lbuf
= {0};
608 * print inode type header region
610 * bcopy to ensure 8-byte alignment for the long longs in
611 * xfs_inode_log_format_t structure
613 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
615 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_inode_log_format_t
), len
));
616 version
= lbuf
.ilf_type
;
618 (*i
)++; /* bump index */
620 if (version
== XFS_LI_5_3_INODE
) {
621 old_f
= (xfs_inode_log_format_t_v1
*)f
;
622 if (len
== sizeof(xfs_inode_log_format_t_v1
)) {
623 printf("5.3 INODE: #regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
624 old_f
->ilf_size
, (unsigned long long)old_f
->ilf_ino
,
625 old_f
->ilf_fields
, old_f
->ilf_dsize
);
627 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
628 printf("5.3 INODE: #regs: %d Not printing rest of data\n",
630 return old_f
->ilf_size
;
633 if (len
== sizeof(xfs_inode_log_format_t
)) {
634 if (version
== XFS_LI_6_1_INODE
)
635 printf("6.1 INODE: ");
636 else printf("INODE: ");
637 printf("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
638 f
->ilf_size
, (unsigned long long)f
->ilf_ino
,
639 f
->ilf_fields
, f
->ilf_dsize
);
640 printf(" blkno: %lld len: %d boff: %d\n",
641 (long long)f
->ilf_blkno
, f
->ilf_len
, f
->ilf_boffset
);
643 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
644 printf("INODE: #regs: %d Not printing rest of data\n",
650 if (*i
>= num_ops
) /* end of LR */
651 return f
->ilf_size
-1;
653 /* core inode comes 2nd */
654 op_head
= (xlog_op_header_t
*)*ptr
;
655 xlog_print_op_header(op_head
, *i
, ptr
);
657 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
658 return f
->ilf_size
-1;
661 bcopy(*ptr
, &dino
, sizeof(dino
));
662 mode
= dino
.di_mode
& IFMT
;
663 size
= (int)dino
.di_size
;
664 xlog_print_trans_inode_core(&dino
);
665 *ptr
+= sizeof(xfs_dinode_core_t
);
667 if (*i
== num_ops
-1 && f
->ilf_size
== 3) {
671 /* does anything come next */
672 op_head
= (xlog_op_header_t
*)*ptr
;
673 switch (f
->ilf_fields
& XFS_ILOG_NONCORE
) {
674 case XFS_ILOG_DEXT
: {
675 ASSERT(f
->ilf_size
== 3);
677 xlog_print_op_header(op_head
, *i
, ptr
);
678 printf("EXTENTS inode data\n");
679 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
680 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
685 case XFS_ILOG_DBROOT
: {
686 ASSERT(f
->ilf_size
== 3);
688 xlog_print_op_header(op_head
, *i
, ptr
);
689 printf("BTREE inode data\n");
690 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
691 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
696 case XFS_ILOG_DDATA
: {
697 ASSERT(f
->ilf_size
== 3);
699 xlog_print_op_header(op_head
, *i
, ptr
);
700 printf("LOCAL inode data\n");
702 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
704 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
705 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
))
710 ASSERT(f
->ilf_size
== 2);
711 printf("DEV inode: no extra region\n");
714 case XFS_ILOG_UUID
: {
715 ASSERT(f
->ilf_size
== 2);
716 printf("UUID inode: no extra region\n");
720 ASSERT(f
->ilf_size
== 2);
724 xlog_panic("xlog_print_trans_inode: illegal inode type");
728 } /* xlog_print_trans_inode */
732 /******************************************************************************
736 ******************************************************************************
740 xlog_print_lseek(xlog_t
*log
, int fd
, xfs_daddr_t blkno
, int whence
)
742 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
745 if (whence
== SEEK_SET
)
746 offset
= BBTOOFF64(blkno
+log
->l_logBBstart
);
748 offset
= BBTOOFF64(blkno
);
749 if (lseek64(fd
, offset
, whence
) < 0) {
750 fprintf(stderr
, "%s: lseek64 to %llu failed: %s\n",
751 progname
, (unsigned long long)offset
, strerror(errno
));
754 } /* xlog_print_lseek */
758 print_lsn(xfs_caddr_t string
,
762 printf("%s: %u,%u", string
,
763 CYCLE_LSN(*lsn
, arch
), BLOCK_LSN(*lsn
, arch
));
768 xlog_print_record(int fd
,
772 xfs_caddr_t
*partial_buf
,
773 xlog_rec_header_t
*rhead
)
775 xlog_op_header_t
*op_head
;
776 xlog_rec_header_t
*rechead
;
777 xfs_caddr_t buf
, ptr
;
789 /* read_len must read up to some block boundary */
790 read_len
= (int) BBTOB(BTOBB(len
));
792 /* read_type => don't malloc() new buffer, use old one */
793 if (*read_type
== FULL_READ
) {
794 if ((ptr
= buf
= (xfs_caddr_t
)malloc(read_len
)) == NULL
) {
795 fprintf(stderr
, "xlog_print_record: malloc failed\n");
799 read_len
-= *read_type
;
800 buf
= (xfs_caddr_t
)((__psint_t
)(*partial_buf
) + (__psint_t
)(*read_type
));
803 if ((ret
= (int) read(fd
, buf
, read_len
)) == -1) {
804 fprintf(stderr
, "xlog_print_record: read error\n");
807 /* Did we overflow the end? */
808 if (*read_type
== FULL_READ
&&
809 BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)+BTOBB(read_len
) >= logBBsize
) {
810 *read_type
= BBTOB(logBBsize
-BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)-1);
815 /* Did we read everything? */
816 if ((ret
== 0 && read_len
!= 0) || ret
!= read_len
) {
821 if (*read_type
!= FULL_READ
)
822 read_len
+= *read_type
;
824 /* Everything read in. Start from beginning of buffer */
826 for (i
= 0; ptr
< buf
+ read_len
; ptr
+= BBSIZE
, i
++) {
827 rechead
= (xlog_rec_header_t
*)ptr
;
828 if (INT_GET(rechead
->h_magicno
, ARCH_CONVERT
) == XLOG_HEADER_MAGIC_NUM
) {
829 xlog_print_lseek(0, fd
, -read_len
+i
*BBSIZE
, SEEK_CUR
);
833 if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) !=
834 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
)) {
835 if (*read_type
== FULL_READ
)
837 else if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) + 1 !=
838 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
))
842 INT_SET(*(uint
*)ptr
, ARCH_CONVERT
,
843 INT_GET(rhead
->h_cycle_data
[i
], ARCH_CONVERT
));
846 for (i
=0; i
<num_ops
; i
++) {
847 print_xlog_op_line();
848 op_head
= (xlog_op_header_t
*)ptr
;
849 xlog_print_op_header(op_head
, i
, &ptr
);
851 /* print transaction data */
853 ((XLOG_SET(op_head
->oh_flags
, XLOG_WAS_CONT_TRANS
) ||
854 XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) &&
855 INT_GET(op_head
->oh_len
, ARCH_CONVERT
) == 0)) {
856 for (n
= 0; n
< INT_GET(op_head
->oh_len
, ARCH_CONVERT
); n
++) {
863 if (xlog_print_find_tid(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
),
864 op_head
->oh_flags
& XLOG_WAS_CONT_TRANS
)) {
865 printf("Left over region from split log item\n");
866 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
869 if (INT_GET(op_head
->oh_len
, ARCH_CONVERT
) != 0) {
870 if (*(uint
*)ptr
== XFS_TRANS_HEADER_MAGIC
) {
871 skip
= xlog_print_trans_header(&ptr
,
872 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
874 switch (*(unsigned short *)ptr
) {
879 skip
= xlog_print_trans_buffer(&ptr
,
880 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
884 case XFS_LI_5_3_INODE
:
885 case XFS_LI_6_1_INODE
:
887 skip
= xlog_print_trans_inode(&ptr
,
888 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
893 skip
= xlog_print_trans_efi(&ptr
,
894 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
898 skip
= xlog_print_trans_efd(&ptr
,
899 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
902 case XLOG_UNMOUNT_TYPE
: {
903 printf("Unmount filesystem\n");
908 fprintf(stderr
, "%s: unknown log operation type (%x)\n",
909 progname
, *(unsigned short *)ptr
);
911 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
916 xlog_print_add_to_trans(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
), skip
);
922 } /* xlog_print_record */
926 xlog_print_rec_head(xlog_rec_header_t
*head
, int *len
)
933 return INT_GET(head
->h_num_logops
, ARCH_CONVERT
);
935 if (INT_ISZERO(head
->h_magicno
, ARCH_CONVERT
))
938 if (INT_GET(head
->h_magicno
, ARCH_CONVERT
) != XLOG_HEADER_MAGIC_NUM
) {
939 printf("Header 0x%x wanted 0x%x\n",
940 INT_GET(head
->h_magicno
, ARCH_CONVERT
),
941 XLOG_HEADER_MAGIC_NUM
);
945 datalen
=INT_GET(head
->h_len
, ARCH_CONVERT
);
946 bbs
=(datalen
/BBSIZE
)+(datalen
%BBSIZE
)?1:0;
948 printf("cycle: %d version: %d ",
949 INT_GET(head
->h_cycle
, ARCH_CONVERT
),
950 INT_GET(head
->h_version
, ARCH_CONVERT
));
951 print_lsn(" lsn", &head
->h_lsn
, ARCH_CONVERT
);
952 print_lsn(" tail_lsn", &head
->h_tail_lsn
, ARCH_CONVERT
);
954 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
956 INT_GET(head
->h_prev_block
, ARCH_CONVERT
),
957 INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
959 if (print_overwrite
) {
960 printf("cycle num overwrites: ");
961 for (i
=0; i
< bbs
; i
++)
964 INT_GET(head
->h_cycle_data
[i
], ARCH_CONVERT
));
968 uuid_unparse(head
->h_fs_uuid
, uub
);
969 printf("uuid: %s format: ", uub
);
970 switch (INT_GET(head
->h_fmt
, ARCH_CONVERT
)) {
971 case XLOG_FMT_UNKNOWN
:
974 case XLOG_FMT_LINUX_LE
:
975 printf("little endian linux\n");
977 case XLOG_FMT_LINUX_BE
:
978 printf("big endian linux\n");
980 case XLOG_FMT_IRIX_BE
:
981 printf("big endian irix\n");
984 printf("? (%d)\n", INT_GET(head
->h_fmt
, ARCH_CONVERT
));
988 *len
= INT_GET(head
->h_len
, ARCH_CONVERT
);
989 return(INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
990 } /* xlog_print_rec_head */
993 print_xlog_bad_zeroed(xfs_daddr_t blkno
)
996 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
1000 xlog_exit("Bad log - data after zeroed blocks");
1001 } /* print_xlog_bad_zeroed */
1004 print_xlog_bad_header(xfs_daddr_t blkno
, xfs_caddr_t buf
)
1007 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
1008 GET_CYCLE(buf
, ARCH_CONVERT
), (long long)blkno
);
1011 xlog_exit("Bad log record header");
1012 } /* print_xlog_bad_header */
1015 print_xlog_bad_data(xfs_daddr_t blkno
)
1018 printf("* ERROR: data block=%-21lld *\n",
1022 xlog_exit("Bad data in log");
1023 } /* print_xlog_bad_data */
1027 * This code is gross and needs to be rewritten.
1029 void xfs_log_print(xlog_t
*log
,
1031 int print_block_start
)
1033 char hbuf
[XLOG_HEADER_SIZE
];
1035 xfs_daddr_t block_end
= 0, block_start
, blkno
, error
;
1036 int read_type
= FULL_READ
;
1037 xfs_caddr_t partial_buf
;
1040 logBBsize
= log
->l_logBBsize
;
1043 * Normally, block_start and block_end are the same value since we
1044 * are printing the entire log. However, if the start block is given,
1045 * we still end at the end of the logical log.
1047 if (error
= xlog_print_find_oldest(log
, &block_end
)) {
1048 fprintf(stderr
, "%s: problem finding oldest LR\n", progname
);
1051 if (print_block_start
== -1)
1052 block_start
= block_end
;
1054 block_start
= print_block_start
;
1055 xlog_print_lseek(log
, fd
, block_start
, SEEK_SET
);
1056 blkno
= block_start
;
1059 if (read(fd
, hbuf
, 512) == 0) {
1060 printf("%s: physical end of log\n", progname
);
1061 print_xlog_record_line();
1064 if (print_only_data
) {
1065 printf("BLKNO: %lld\n", (long long)blkno
);
1066 xlog_recover_print_data(hbuf
, 512);
1070 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1073 if (zeroed
&& num_ops
!= ZEROED_LOG
) {
1074 printf("%s: after %d zeroed blocks\n", progname
, zeroed
);
1075 /* once we find zeroed blocks - that's all we expect */
1076 print_xlog_bad_zeroed(blkno
-1);
1077 /* reset count since we're assuming previous zeroed blocks
1083 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1084 if (num_ops
== ZEROED_LOG
) {
1087 print_xlog_bad_header(blkno
-1, hbuf
);
1093 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
, &partial_buf
,
1094 (xlog_rec_header_t
*)hbuf
);
1097 blkno
+= BTOBB(len
);
1098 if (print_block_start
!= -1 &&
1099 blkno
>= block_end
) /* If start specified, we */
1100 goto end
; /* end early */
1104 print_xlog_bad_data(blkno
-1);
1105 if (print_block_start
!= -1 &&
1106 blkno
>= block_end
) /* If start specified, */
1107 goto end
; /* we end early */
1108 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1111 case PARTIAL_READ
: {
1112 print_xlog_record_line();
1113 printf("%s: physical end of log\n", progname
);
1114 print_xlog_record_line();
1116 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1118 * We may have hit the end of the log when we started at 0.
1119 * In this case, just end.
1121 if (block_start
== 0)
1123 goto partial_log_read
;
1125 default: xlog_panic("illegal value");
1127 print_xlog_record_line();
1129 if (blkno
>= logBBsize
) {
1131 printf("%s: skipped %d zeroed blocks\n", progname
, zeroed
);
1132 if (zeroed
== logBBsize
)
1133 printf("%s: totally zeroed log\n", progname
);
1137 printf("%s: physical end of log\n", progname
);
1138 print_xlog_record_line();
1143 /* Do we need to print the first part of physical log? */
1144 if (block_start
!= 0) {
1146 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1148 if (read(fd
, hbuf
, 512) == 0) {
1149 xlog_panic("xlog_find_head: bad read");
1151 if (print_only_data
) {
1152 printf("BLKNO: %lld\n", (long long)blkno
);
1153 xlog_recover_print_data(hbuf
, 512);
1157 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1160 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1161 /* we only expect zeroed log entries at the end
1162 * of the _physical_ log, so treat them the same
1163 * as bad blocks here
1165 print_xlog_bad_header(blkno
-1, hbuf
);
1167 if (blkno
>= block_end
)
1172 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
,
1173 &partial_buf
, (xlog_rec_header_t
*)hbuf
);
1174 if (read_type
!= FULL_READ
)
1176 read_type
= FULL_READ
;
1178 blkno
+= BTOBB(len
);
1180 print_xlog_bad_data(blkno
-1);
1181 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1184 print_xlog_record_line();
1186 if (blkno
>= block_end
)
1192 printf("%s: logical end of log\n", progname
);
1193 print_xlog_record_line();