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
, blkno
, 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",
423 INT_GET(dq
->d_blk_hardlimit
, ARCH_CONVERT
),
424 INT_GET(dq
->d_blk_softlimit
, ARCH_CONVERT
));
425 printf("blk count: %llu warns: %d timer: %d\n",
426 INT_GET(dq
->d_bcount
, ARCH_CONVERT
),
427 INT_GET(dq
->d_bwarns
, ARCH_CONVERT
),
428 INT_GET(dq
->d_btimer
, ARCH_CONVERT
));
429 printf("ino limits hard: %llu soft: %llu\n",
430 INT_GET(dq
->d_ino_hardlimit
, ARCH_CONVERT
),
431 INT_GET(dq
->d_ino_softlimit
, ARCH_CONVERT
));
432 printf("ino count: %llu warns: %d timer: %d\n",
433 INT_GET(dq
->d_icount
, ARCH_CONVERT
),
434 INT_GET(dq
->d_iwarns
, ARCH_CONVERT
),
435 INT_GET(dq
->d_itimer
, ARCH_CONVERT
));
438 printf("BUF DATA\n");
440 uint
*dp
= (uint
*)*ptr
;
441 int nums
= INT_GET(head
->oh_len
, ARCH_CONVERT
) >> 2;
456 *ptr
+= INT_GET(head
->oh_len
, ARCH_CONVERT
);
458 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
461 } /* xlog_print_trans_buffer */
465 xlog_print_trans_efd(xfs_caddr_t
*ptr
, uint len
)
467 xfs_efd_log_format_t
*f
;
470 xfs_efd_log_format_t lbuf
;
473 * bcopy to ensure 8-byte alignment for the long longs in
474 * xfs_efd_log_format_t structure
476 bcopy(*ptr
, &lbuf
, sizeof(xfs_efd_log_format_t
));
479 if (len
>= sizeof(xfs_efd_log_format_t
)) {
480 printf("EFD: #regs: %d num_extents: %d id: 0x%llx\n",
481 f
->efd_size
, f
->efd_nextents
, f
->efd_efi_id
);
483 for (i
=0; i
< f
->efd_size
; i
++) {
484 printf("(s: 0x%llx, l: %d) ", ex
->ext_start
, ex
->ext_len
);
485 if (i
% 4 == 3) printf("\n");
488 if (i
% 4 != 0) printf("\n");
491 printf("EFD: Not enough data to decode further\n");
494 } /* xlog_print_trans_efd */
498 xlog_print_trans_efi(xfs_caddr_t
*ptr
, uint len
)
500 xfs_efi_log_format_t
*f
;
503 xfs_efi_log_format_t lbuf
;
506 * bcopy to ensure 8-byte alignment for the long longs in
507 * xfs_efi_log_format_t structure
509 bcopy(*ptr
, &lbuf
, sizeof(xfs_efi_log_format_t
));
512 if (len
>= sizeof(xfs_efi_log_format_t
)) {
513 printf("EFI: #regs: %d num_extents: %d id: 0x%llx\n",
514 f
->efi_size
, f
->efi_nextents
, f
->efi_id
);
516 for (i
=0; i
< f
->efi_size
; i
++) {
517 printf("(s: 0x%llx, l: %d) ", ex
->ext_start
, ex
->ext_len
);
518 if (i
% 4 == 3) printf("\n");
521 if (i
% 4 != 0) printf("\n");
524 printf("EFI: Not enough data to decode further\n");
527 } /* xlog_print_trans_efi */
532 xlog_print_trans_inode_core(xfs_dinode_core_t
*ip
)
534 printf("INODE CORE\n");
535 printf("magic 0x%hx mode 0%ho version %d format %d\n",
536 ip
->di_magic
, ip
->di_mode
, (int)ip
->di_version
,
538 printf("nlink %hd uid %d gid %d\n",
539 ip
->di_nlink
, ip
->di_uid
, ip
->di_gid
);
540 printf("atime 0x%x mtime 0x%x ctime 0x%x\n",
541 ip
->di_atime
.t_sec
, ip
->di_mtime
.t_sec
, ip
->di_ctime
.t_sec
);
542 printf("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n",
543 ip
->di_size
, ip
->di_nblocks
, ip
->di_extsize
, ip
->di_nextents
);
544 printf("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n",
545 ip
->di_anextents
, (int)ip
->di_forkoff
, ip
->di_dmevmask
,
547 printf("flags 0x%x gen 0x%x\n",
548 ip
->di_flags
, ip
->di_gen
);
552 xlog_print_dir_sf(xfs_dir_shortform_t
*sfp
, int size
)
558 xfs_dir_sf_entry_t
*sfep
;
560 /* XXX need to determine whether this is v1 or v2, then
561 print appropriate structure */
563 printf("SHORTFORM DIRECTORY size %d\n",
565 /* bail out for now */
569 printf("SHORTFORM DIRECTORY size %d count %d\n",
570 size
, sfp
->hdr
.count
);
571 bcopy(&(sfp
->hdr
.parent
), &ino
, sizeof(ino
));
572 printf(".. ino 0x%llx\n", INT_GET(ino
, ARCH_CONVERT
));
574 count
= (uint
)(sfp
->hdr
.count
);
575 sfep
= &(sfp
->list
[0]);
576 for (i
= 0; i
< count
; i
++) {
577 bcopy(&(sfep
->inumber
), &ino
, sizeof(ino
));
578 bcopy((sfep
->name
), namebuf
, sfep
->namelen
);
579 namebuf
[sfep
->namelen
] = '\0';
580 printf("%s ino 0x%llx namelen %d\n",
581 namebuf
, ino
, sfep
->namelen
);
582 sfep
= XFS_DIR_SF_NEXTENTRY(sfep
);
587 xlog_print_trans_inode(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
589 xfs_inode_log_format_t
*f
;
590 xfs_inode_log_format_t_v1
*old_f
;
591 xfs_dinode_core_t dino
;
592 xlog_op_header_t
*op_head
;
594 xfs_inode_log_format_t lbuf
= {0};
599 * print inode type header region
601 * bcopy to ensure 8-byte alignment for the long longs in
602 * xfs_inode_log_format_t structure
604 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
606 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_inode_log_format_t
), len
));
607 version
= lbuf
.ilf_type
;
609 (*i
)++; /* bump index */
611 if (version
== XFS_LI_5_3_INODE
) {
612 old_f
= (xfs_inode_log_format_t_v1
*)f
;
613 if (len
== sizeof(xfs_inode_log_format_t_v1
)) {
614 printf("5.3 INODE: #regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
615 old_f
->ilf_size
, old_f
->ilf_ino
,
616 old_f
->ilf_fields
, old_f
->ilf_dsize
);
618 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
619 printf("5.3 INODE: #regs: %d Not printing rest of data\n",
621 return old_f
->ilf_size
;
624 if (len
== sizeof(xfs_inode_log_format_t
)) {
625 if (version
== XFS_LI_6_1_INODE
)
626 printf("6.1 INODE: ");
627 else printf("INODE: ");
628 printf("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
629 f
->ilf_size
, f
->ilf_ino
, f
->ilf_fields
, f
->ilf_dsize
);
630 printf(" blkno: %lld len: %d boff: %d\n",
631 f
->ilf_blkno
, f
->ilf_len
, f
->ilf_boffset
);
633 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
634 printf("INODE: #regs: %d Not printing rest of data\n",
640 if (*i
>= num_ops
) /* end of LR */
641 return f
->ilf_size
-1;
643 /* core inode comes 2nd */
644 op_head
= (xlog_op_header_t
*)*ptr
;
645 xlog_print_op_header(op_head
, *i
, ptr
);
647 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
648 return f
->ilf_size
-1;
651 bcopy(*ptr
, &dino
, sizeof(dino
));
652 mode
= dino
.di_mode
& IFMT
;
653 size
= (int)dino
.di_size
;
654 xlog_print_trans_inode_core(&dino
);
655 *ptr
+= sizeof(xfs_dinode_core_t
);
657 if (*i
== num_ops
-1 && f
->ilf_size
== 3) {
661 /* does anything come next */
662 op_head
= (xlog_op_header_t
*)*ptr
;
663 switch (f
->ilf_fields
& XFS_ILOG_NONCORE
) {
664 case XFS_ILOG_DEXT
: {
665 ASSERT(f
->ilf_size
== 3);
667 xlog_print_op_header(op_head
, *i
, ptr
);
668 printf("EXTENTS inode data\n");
669 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
670 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
675 case XFS_ILOG_DBROOT
: {
676 ASSERT(f
->ilf_size
== 3);
678 xlog_print_op_header(op_head
, *i
, ptr
);
679 printf("BTREE inode data\n");
680 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
681 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
686 case XFS_ILOG_DDATA
: {
687 ASSERT(f
->ilf_size
== 3);
689 xlog_print_op_header(op_head
, *i
, ptr
);
690 printf("LOCAL inode data\n");
692 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
694 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
695 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
))
700 ASSERT(f
->ilf_size
== 2);
701 printf("DEV inode: no extra region\n");
704 case XFS_ILOG_UUID
: {
705 ASSERT(f
->ilf_size
== 2);
706 printf("UUID inode: no extra region\n");
710 ASSERT(f
->ilf_size
== 2);
714 xlog_panic("xlog_print_trans_inode: illegal inode type");
718 } /* xlog_print_trans_inode */
722 /******************************************************************************
726 ******************************************************************************
730 xlog_print_lseek(xlog_t
*log
, int fd
, xfs_daddr_t blkno
, int whence
)
732 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
735 if (whence
== SEEK_SET
)
736 offset
= BBTOOFF64(blkno
+log
->l_logBBstart
);
738 offset
= BBTOOFF64(blkno
);
739 if (lseek64(fd
, offset
, whence
) < 0) {
740 fprintf(stderr
, "%s: lseek64 to %llu failed: %s\n",
741 progname
, offset
, strerror(errno
));
744 } /* xlog_print_lseek */
748 print_lsn(xfs_caddr_t string
,
752 printf("%s: %u,%u", string
,
753 CYCLE_LSN(*lsn
, arch
), BLOCK_LSN(*lsn
, arch
));
758 xlog_print_record(int fd
,
762 xfs_caddr_t
*partial_buf
,
763 xlog_rec_header_t
*rhead
)
765 xlog_op_header_t
*op_head
;
766 xlog_rec_header_t
*rechead
;
767 xfs_caddr_t buf
, ptr
;
779 /* read_len must read up to some block boundary */
780 read_len
= (int) BBTOB(BTOBB(len
));
782 /* read_type => don't malloc() new buffer, use old one */
783 if (*read_type
== FULL_READ
) {
784 if ((ptr
= buf
= (xfs_caddr_t
)malloc(read_len
)) == NULL
) {
785 fprintf(stderr
, "xlog_print_record: malloc failed\n");
789 read_len
-= *read_type
;
790 buf
= (xfs_caddr_t
)((__psint_t
)(*partial_buf
) + (__psint_t
)(*read_type
));
793 if ((ret
= (int) read(fd
, buf
, read_len
)) == -1) {
794 fprintf(stderr
, "xlog_print_record: read error\n");
797 /* Did we overflow the end? */
798 if (*read_type
== FULL_READ
&&
799 BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)+BTOBB(read_len
) >= logBBsize
) {
800 *read_type
= BBTOB(logBBsize
-BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)-1);
805 /* Did we read everything? */
806 if ((ret
== 0 && read_len
!= 0) || ret
!= read_len
) {
811 if (*read_type
!= FULL_READ
)
812 read_len
+= *read_type
;
814 /* Everything read in. Start from beginning of buffer */
816 for (i
= 0; ptr
< buf
+ read_len
; ptr
+= BBSIZE
, i
++) {
817 rechead
= (xlog_rec_header_t
*)ptr
;
818 if (INT_GET(rechead
->h_magicno
, ARCH_CONVERT
) == XLOG_HEADER_MAGIC_NUM
) {
819 xlog_print_lseek(0, fd
, -read_len
+i
*BBSIZE
, SEEK_CUR
);
823 if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) !=
824 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
)) {
825 if (*read_type
== FULL_READ
)
827 else if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) + 1 !=
828 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
))
832 INT_SET(*(uint
*)ptr
, ARCH_CONVERT
,
833 INT_GET(rhead
->h_cycle_data
[i
], ARCH_CONVERT
));
836 for (i
=0; i
<num_ops
; i
++) {
837 print_xlog_op_line();
838 op_head
= (xlog_op_header_t
*)ptr
;
839 xlog_print_op_header(op_head
, i
, &ptr
);
841 /* print transaction data */
843 ((XLOG_SET(op_head
->oh_flags
, XLOG_WAS_CONT_TRANS
) ||
844 XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) &&
845 INT_GET(op_head
->oh_len
, ARCH_CONVERT
) == 0)) {
846 for (n
= 0; n
< INT_GET(op_head
->oh_len
, ARCH_CONVERT
); n
++) {
853 if (xlog_print_find_tid(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
),
854 op_head
->oh_flags
& XLOG_WAS_CONT_TRANS
)) {
855 printf("Left over region from split log item\n");
856 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
859 if (INT_GET(op_head
->oh_len
, ARCH_CONVERT
) != 0) {
860 if (*(uint
*)ptr
== XFS_TRANS_HEADER_MAGIC
) {
861 skip
= xlog_print_trans_header(&ptr
,
862 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
864 switch (*(unsigned short *)ptr
) {
869 skip
= xlog_print_trans_buffer(&ptr
,
870 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
874 case XFS_LI_5_3_INODE
:
875 case XFS_LI_6_1_INODE
:
877 skip
= xlog_print_trans_inode(&ptr
,
878 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
883 skip
= xlog_print_trans_efi(&ptr
,
884 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
888 skip
= xlog_print_trans_efd(&ptr
,
889 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
892 case XLOG_UNMOUNT_TYPE
: {
893 printf("Unmount filesystem\n");
898 fprintf(stderr
, "%s: unknown log operation type (%x)\n",
899 progname
, *(unsigned short *)ptr
);
901 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
906 xlog_print_add_to_trans(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
), skip
);
912 } /* xlog_print_record */
916 xlog_print_rec_head(xlog_rec_header_t
*head
, int *len
)
923 return INT_GET(head
->h_num_logops
, ARCH_CONVERT
);
925 if (INT_ISZERO(head
->h_magicno
, ARCH_CONVERT
))
928 if (INT_GET(head
->h_magicno
, ARCH_CONVERT
) != XLOG_HEADER_MAGIC_NUM
) {
929 printf("Header 0x%x wanted 0x%x\n",
930 INT_GET(head
->h_magicno
, ARCH_CONVERT
),
931 XLOG_HEADER_MAGIC_NUM
);
935 datalen
=INT_GET(head
->h_len
, ARCH_CONVERT
);
936 bbs
=(datalen
/BBSIZE
)+(datalen
%BBSIZE
)?1:0;
938 printf("cycle: %d version: %d ",
939 INT_GET(head
->h_cycle
, ARCH_CONVERT
),
940 INT_GET(head
->h_version
, ARCH_CONVERT
));
941 print_lsn(" lsn", &head
->h_lsn
, ARCH_CONVERT
);
942 print_lsn(" tail_lsn", &head
->h_tail_lsn
, ARCH_CONVERT
);
944 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
946 INT_GET(head
->h_prev_block
, ARCH_CONVERT
),
947 INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
949 if (print_overwrite
) {
950 printf("cycle num overwrites: ");
951 for (i
=0; i
< bbs
; i
++)
954 INT_GET(head
->h_cycle_data
[i
], ARCH_CONVERT
));
958 uuid_unparse(head
->h_fs_uuid
, uub
);
959 printf("uuid: %s format: ", uub
);
960 switch (INT_GET(head
->h_fmt
, ARCH_CONVERT
)) {
961 case XLOG_FMT_UNKNOWN
:
964 case XLOG_FMT_LINUX_LE
:
965 printf("little endian linux\n");
967 case XLOG_FMT_LINUX_BE
:
968 printf("big endian linux\n");
970 case XLOG_FMT_IRIX_BE
:
971 printf("big endian irix\n");
974 printf("? (%d)\n", INT_GET(head
->h_fmt
, ARCH_CONVERT
));
978 *len
= INT_GET(head
->h_len
, ARCH_CONVERT
);
979 return(INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
980 } /* xlog_print_rec_head */
983 print_xlog_bad_zeroed(xfs_daddr_t blkno
)
986 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
990 xlog_exit("Bad log - data after zeroed blocks");
991 } /* print_xlog_bad_zeroed */
994 print_xlog_bad_header(xfs_daddr_t blkno
, xfs_caddr_t buf
)
997 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
998 GET_CYCLE(buf
, ARCH_CONVERT
), (__int64_t
)blkno
);
1001 xlog_exit("Bad log record header");
1002 } /* print_xlog_bad_header */
1005 print_xlog_bad_data(xfs_daddr_t blkno
)
1008 printf("* ERROR: data block=%-21lld *\n",
1012 xlog_exit("Bad data in log");
1013 } /* print_xlog_bad_data */
1017 * This code is gross and needs to be rewritten.
1019 void xfs_log_print(xlog_t
*log
,
1021 int print_block_start
)
1023 char hbuf
[XLOG_HEADER_SIZE
];
1025 xfs_daddr_t block_end
= 0, block_start
, blkno
, error
;
1026 int read_type
= FULL_READ
;
1027 xfs_caddr_t partial_buf
;
1030 logBBsize
= log
->l_logBBsize
;
1033 * Normally, block_start and block_end are the same value since we
1034 * are printing the entire log. However, if the start block is given,
1035 * we still end at the end of the logical log.
1037 if (error
= xlog_print_find_oldest(log
, &block_end
)) {
1038 fprintf(stderr
, "%s: problem finding oldest LR\n", progname
);
1041 if (print_block_start
== -1)
1042 block_start
= block_end
;
1044 block_start
= print_block_start
;
1045 xlog_print_lseek(log
, fd
, block_start
, SEEK_SET
);
1046 blkno
= block_start
;
1049 if (read(fd
, hbuf
, 512) == 0) {
1050 printf("%s: physical end of log\n", progname
);
1051 print_xlog_record_line();
1054 if (print_only_data
) {
1055 printf("BLKNO: %lld\n", (__int64_t
)blkno
);
1056 xlog_recover_print_data(hbuf
, 512);
1060 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1063 if (zeroed
&& num_ops
!= ZEROED_LOG
) {
1064 printf("%s: after %d zeroed blocks\n", progname
, zeroed
);
1065 /* once we find zeroed blocks - that's all we expect */
1066 print_xlog_bad_zeroed(blkno
-1);
1067 /* reset count since we're assuming previous zeroed blocks
1073 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1074 if (num_ops
== ZEROED_LOG
) {
1077 print_xlog_bad_header(blkno
-1, hbuf
);
1083 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
, &partial_buf
,
1084 (xlog_rec_header_t
*)hbuf
);
1087 blkno
+= BTOBB(len
);
1088 if (print_block_start
!= -1 &&
1089 blkno
>= block_end
) /* If start specified, we */
1090 goto end
; /* end early */
1094 print_xlog_bad_data(blkno
-1);
1095 if (print_block_start
!= -1 &&
1096 blkno
>= block_end
) /* If start specified, */
1097 goto end
; /* we end early */
1098 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1101 case PARTIAL_READ
: {
1102 print_xlog_record_line();
1103 printf("%s: physical end of log\n", progname
);
1104 print_xlog_record_line();
1106 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1108 * We may have hit the end of the log when we started at 0.
1109 * In this case, just end.
1111 if (block_start
== 0)
1113 goto partial_log_read
;
1115 default: xlog_panic("illegal value");
1117 print_xlog_record_line();
1119 if (blkno
>= logBBsize
) {
1121 printf("%s: skipped %d zeroed blocks\n", progname
, zeroed
);
1122 if (zeroed
== logBBsize
)
1123 printf("%s: totally zeroed log\n", progname
);
1127 printf("%s: physical end of log\n", progname
);
1128 print_xlog_record_line();
1133 /* Do we need to print the first part of physical log? */
1134 if (block_start
!= 0) {
1136 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1138 if (read(fd
, hbuf
, 512) == 0) {
1139 xlog_panic("xlog_find_head: bad read");
1141 if (print_only_data
) {
1142 printf("BLKNO: %lld\n", (__int64_t
)blkno
);
1143 xlog_recover_print_data(hbuf
, 512);
1147 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1150 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1151 /* we only expect zeroed log entries at the end
1152 * of the _physical_ log, so treat them the same
1153 * as bad blocks here
1155 print_xlog_bad_header(blkno
-1, hbuf
);
1157 if (blkno
>= block_end
)
1162 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
,
1163 &partial_buf
, (xlog_rec_header_t
*)hbuf
);
1164 if (read_type
!= FULL_READ
)
1166 read_type
= FULL_READ
;
1168 blkno
+= BTOBB(len
);
1170 print_xlog_bad_data(blkno
-1);
1171 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1174 print_xlog_record_line();
1176 if (blkno
>= block_end
)
1182 printf("%s: logical end of log\n", progname
);
1183 print_xlog_record_line();