2 * Copyright (c) 2000-2001 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 */
224 #if __BYTE_ORDER == __LITTLE_ENDIAN
226 magic_c
[3], magic_c
[2], magic_c
[1], magic_c
[0]);
229 magic_c
[0], magic_c
[1], magic_c
[2], magic_c
[3]);
232 if (len
!= sizeof(xfs_trans_header_t
)) {
233 printf(" Not enough data to decode further\n");
236 h
= (xfs_trans_header_t
*)cptr
;
237 printf(" type: %s tid: %x num_items: %d\n",
238 trans_type
[h
->th_type
], h
->th_tid
, h
->th_num_items
);
240 } /* xlog_print_trans_header */
244 xlog_print_trans_buffer(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
246 xfs_buf_log_format_t
*f
;
247 xfs_buf_log_format_v1_t
*old_f
;
250 xfs_disk_dquot_t
*dq
;
251 xlog_op_header_t
*head
= 0;
254 int bucket
, col
, buckets
;
256 xfs_buf_log_format_t lbuf
;
257 int size
, blen
, map_size
, struct_size
;
261 * bcopy to ensure 8-byte alignment for the long longs in
262 * buf_log_format_t structure
264 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_buf_log_format_t
), len
));
268 if (f
->blf_type
== XFS_LI_BUF
) {
269 blkno
= f
->blf_blkno
;
272 map_size
= f
->blf_map_size
;
273 struct_size
= sizeof(xfs_buf_log_format_t
);
275 old_f
= (xfs_buf_log_format_v1_t
*)f
;
276 blkno
= old_f
->blf_blkno
;
277 size
= old_f
->blf_size
;
278 blen
= old_f
->blf_len
;
279 map_size
= old_f
->blf_map_size
;
280 struct_size
= sizeof(xfs_buf_log_format_v1_t
);
282 switch (f
->blf_type
) {
293 printf("UNKNOWN BUF: ");
296 if (len
>= struct_size
) {
297 ASSERT((len
- sizeof(struct_size
)) % sizeof(int) == 0);
298 printf("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d\n",
299 size
, (long long)blkno
, (unsigned long long)blkno
, blen
, map_size
);
303 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
304 printf("#regs: %d Not printing rest of data\n", f
->blf_size
);
309 /* Check if all regions in this log item were in the given LR ptr */
310 if (*i
+num
> num_ops
-1) {
311 skip
= num
- (num_ops
-1-*i
);
318 head
= (xlog_op_header_t
*)*ptr
;
319 xlog_print_op_header(head
, *i
, ptr
);
321 printf("SUPER BLOCK Buffer: ");
322 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) < 4*8) {
323 printf("Out of space\n");
327 * bcopy because *ptr may not be 8-byte aligned
329 bcopy(*ptr
, &x
, sizeof(long long));
330 bcopy(*ptr
+8, &y
, sizeof(long long));
331 printf("icount: %lld ifree: %lld ",
332 INT_GET(x
, ARCH_CONVERT
),
333 INT_GET(y
, ARCH_CONVERT
));
334 bcopy(*ptr
+16, &x
, sizeof(long long));
335 bcopy(*ptr
+24, &y
, sizeof(long long));
336 printf("fdblks: %lld frext: %lld\n",
337 INT_GET(x
, ARCH_CONVERT
),
338 INT_GET(y
, ARCH_CONVERT
));
341 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_AGI_MAGIC
) {
342 agi
= (xfs_agi_t
*)(*ptr
);
343 printf("AGI Buffer: XAGI ");
344 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) <
346 XFS_AGI_UNLINKED_BUCKETS
*sizeof(xfs_agino_t
)) {
347 printf("out of space\n");
351 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
));
352 printf("seq#: %d len: %d cnt: %d root: %d\n",
353 INT_GET(agi
->agi_seqno
, ARCH_CONVERT
),
354 INT_GET(agi
->agi_length
, ARCH_CONVERT
),
355 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
356 INT_GET(agi
->agi_root
, ARCH_CONVERT
));
357 printf("level: %d free#: 0x%x newino: 0x%x\n",
358 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
359 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
360 INT_GET(agi
->agi_newino
, ARCH_CONVERT
));
361 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) == 128) {
363 } else if (INT_GET(head
->oh_len
, ARCH_CONVERT
) == 256) {
366 if (head
->oh_flags
& XLOG_CONTINUE_TRANS
) {
367 printf("AGI unlinked data skipped ");
368 printf("(CONTINUE set, no space)\n");
371 buckets
= XFS_AGI_UNLINKED_BUCKETS
;
373 for (bucket
= 0; bucket
< buckets
;) {
374 printf("bucket[%d - %d]: ", bucket
, bucket
+3);
375 for (col
= 0; col
< 4; col
++, bucket
++) {
376 if (bucket
< buckets
) {
378 INT_GET(agi
->agi_unlinked
[bucket
], ARCH_CONVERT
));
384 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_AGF_MAGIC
) {
385 agf
= (xfs_agf_t
*)(*ptr
);
386 printf("AGF Buffer: XAGF ");
387 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) < sizeof(xfs_agf_t
)) {
388 printf("Out of space\n");
391 printf("ver: %d seq#: %d len: %d \n",
392 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
),
393 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
394 INT_GET(agf
->agf_length
, ARCH_CONVERT
));
395 printf("root BNO: %d CNT: %d\n",
396 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNOi
],
398 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNTi
],
400 printf("level BNO: %d CNT: %d\n",
401 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNOi
],
403 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNTi
],
405 printf("1st: %d last: %d cnt: %d "
406 "freeblks: %d longest: %d\n",
407 INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
),
408 INT_GET(agf
->agf_fllast
, ARCH_CONVERT
),
409 INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
410 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
411 INT_GET(agf
->agf_longest
, ARCH_CONVERT
));
413 } else if (INT_GET(*(uint
*)(*ptr
), ARCH_CONVERT
) == XFS_DQUOT_MAGIC
) {
414 dq
= (xfs_disk_dquot_t
*)(*ptr
);
415 printf("DQUOT Buffer: DQ ");
416 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) <
417 sizeof(xfs_disk_dquot_t
)) {
418 printf("Out of space\n");
422 printf("ver: %d flags: 0x%x id: %d \n",
423 INT_GET(dq
->d_version
, ARCH_CONVERT
),
424 INT_GET(dq
->d_flags
, ARCH_CONVERT
),
425 INT_GET(dq
->d_id
, ARCH_CONVERT
));
426 printf("blk limits hard: %llu soft: %llu\n",
428 INT_GET(dq
->d_blk_hardlimit
, ARCH_CONVERT
),
430 INT_GET(dq
->d_blk_softlimit
, ARCH_CONVERT
));
431 printf("blk count: %llu warns: %d timer: %d\n",
433 INT_GET(dq
->d_bcount
, ARCH_CONVERT
),
434 INT_GET(dq
->d_bwarns
, ARCH_CONVERT
),
435 INT_GET(dq
->d_btimer
, ARCH_CONVERT
));
436 printf("ino limits hard: %llu soft: %llu\n",
438 INT_GET(dq
->d_ino_hardlimit
, ARCH_CONVERT
),
440 INT_GET(dq
->d_ino_softlimit
, ARCH_CONVERT
));
441 printf("ino count: %llu warns: %d timer: %d\n",
443 INT_GET(dq
->d_icount
, ARCH_CONVERT
),
444 INT_GET(dq
->d_iwarns
, ARCH_CONVERT
),
445 INT_GET(dq
->d_itimer
, ARCH_CONVERT
));
448 printf("BUF DATA\n");
450 uint
*dp
= (uint
*)*ptr
;
451 int nums
= INT_GET(head
->oh_len
, ARCH_CONVERT
) >> 2;
466 *ptr
+= INT_GET(head
->oh_len
, ARCH_CONVERT
);
468 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
471 } /* xlog_print_trans_buffer */
475 xlog_print_trans_efd(xfs_caddr_t
*ptr
, uint len
)
477 xfs_efd_log_format_t
*f
;
480 xfs_efd_log_format_t lbuf
;
483 * bcopy to ensure 8-byte alignment for the long longs in
484 * xfs_efd_log_format_t structure
486 bcopy(*ptr
, &lbuf
, sizeof(xfs_efd_log_format_t
));
489 if (len
>= sizeof(xfs_efd_log_format_t
)) {
490 printf("EFD: #regs: %d num_extents: %d id: 0x%llx\n",
491 f
->efd_size
, f
->efd_nextents
, (unsigned long long)f
->efd_efi_id
);
493 for (i
=0; i
< f
->efd_size
; i
++) {
494 printf("(s: 0x%llx, l: %d) ",
495 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
496 if (i
% 4 == 3) printf("\n");
499 if (i
% 4 != 0) printf("\n");
502 printf("EFD: Not enough data to decode further\n");
505 } /* xlog_print_trans_efd */
509 xlog_print_trans_efi(xfs_caddr_t
*ptr
, uint len
)
511 xfs_efi_log_format_t
*f
;
514 xfs_efi_log_format_t lbuf
;
517 * bcopy to ensure 8-byte alignment for the long longs in
518 * xfs_efi_log_format_t structure
520 bcopy(*ptr
, &lbuf
, sizeof(xfs_efi_log_format_t
));
523 if (len
>= sizeof(xfs_efi_log_format_t
)) {
524 printf("EFI: #regs: %d num_extents: %d id: 0x%llx\n",
525 f
->efi_size
, f
->efi_nextents
, (unsigned long long)f
->efi_id
);
527 for (i
=0; i
< f
->efi_size
; i
++) {
528 printf("(s: 0x%llx, l: %d) ",
529 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
530 if (i
% 4 == 3) printf("\n");
533 if (i
% 4 != 0) printf("\n");
536 printf("EFI: Not enough data to decode further\n");
539 } /* xlog_print_trans_efi */
543 xlog_print_trans_qoff(xfs_caddr_t
*ptr
, uint len
)
545 xfs_qoff_logformat_t
*f
;
546 xfs_qoff_logformat_t lbuf
;
548 bcopy(*ptr
, &lbuf
, sizeof(xfs_qoff_logformat_t
));
551 if (len
>= sizeof(xfs_qoff_logformat_t
)) {
552 printf("QOFF: #regs: %d flags: 0x%x\n", f
->qf_size
, f
->qf_flags
);
555 printf("QOFF: Not enough data to decode further\n");
558 } /* xlog_print_trans_qoff */
562 xlog_print_trans_inode_core(xfs_dinode_core_t
*ip
)
564 printf("INODE CORE\n");
565 printf("magic 0x%hx mode 0%ho version %d format %d\n",
566 ip
->di_magic
, ip
->di_mode
, (int)ip
->di_version
,
568 printf("nlink %hd uid %d gid %d\n",
569 ip
->di_nlink
, ip
->di_uid
, ip
->di_gid
);
570 printf("atime 0x%x mtime 0x%x ctime 0x%x\n",
571 ip
->di_atime
.t_sec
, ip
->di_mtime
.t_sec
, ip
->di_ctime
.t_sec
);
572 printf("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n",
573 (unsigned long long)ip
->di_size
, (unsigned long long)ip
->di_nblocks
,
574 ip
->di_extsize
, ip
->di_nextents
);
575 printf("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n",
576 ip
->di_anextents
, (int)ip
->di_forkoff
, ip
->di_dmevmask
,
578 printf("flags 0x%x gen 0x%x\n",
579 ip
->di_flags
, ip
->di_gen
);
583 xlog_print_dir_sf(xfs_dir_shortform_t
*sfp
, int size
)
589 xfs_dir_sf_entry_t
*sfep
;
591 /* XXX need to determine whether this is v1 or v2, then
592 print appropriate structure */
594 printf("SHORTFORM DIRECTORY size %d\n",
596 /* bail out for now */
600 printf("SHORTFORM DIRECTORY size %d count %d\n",
601 size
, sfp
->hdr
.count
);
602 bcopy(&(sfp
->hdr
.parent
), &ino
, sizeof(ino
));
603 printf(".. ino 0x%llx\n", (unsigned long long)INT_GET(ino
, ARCH_CONVERT
));
605 count
= (uint
)(sfp
->hdr
.count
);
606 sfep
= &(sfp
->list
[0]);
607 for (i
= 0; i
< count
; i
++) {
608 bcopy(&(sfep
->inumber
), &ino
, sizeof(ino
));
609 bcopy((sfep
->name
), namebuf
, sfep
->namelen
);
610 namebuf
[sfep
->namelen
] = '\0';
611 printf("%s ino 0x%llx namelen %d\n",
612 namebuf
, (unsigned long long)ino
, sfep
->namelen
);
613 sfep
= XFS_DIR_SF_NEXTENTRY(sfep
);
618 xlog_print_trans_inode(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
620 xfs_inode_log_format_t
*f
;
621 xfs_inode_log_format_t_v1
*old_f
;
622 xfs_dinode_core_t dino
;
623 xlog_op_header_t
*op_head
;
625 xfs_inode_log_format_t lbuf
= {0};
630 * print inode type header region
632 * bcopy to ensure 8-byte alignment for the long longs in
633 * xfs_inode_log_format_t structure
635 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
637 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_inode_log_format_t
), len
));
638 version
= lbuf
.ilf_type
;
640 (*i
)++; /* bump index */
642 if (version
== XFS_LI_5_3_INODE
) {
643 old_f
= (xfs_inode_log_format_t_v1
*)f
;
644 if (len
== sizeof(xfs_inode_log_format_t_v1
)) {
645 printf("5.3 INODE: #regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
646 old_f
->ilf_size
, (unsigned long long)old_f
->ilf_ino
,
647 old_f
->ilf_fields
, old_f
->ilf_dsize
);
649 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
650 printf("5.3 INODE: #regs: %d Not printing rest of data\n",
652 return old_f
->ilf_size
;
655 if (len
== sizeof(xfs_inode_log_format_t
)) {
656 if (version
== XFS_LI_6_1_INODE
)
657 printf("6.1 INODE: ");
658 else printf("INODE: ");
659 printf("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
660 f
->ilf_size
, (unsigned long long)f
->ilf_ino
,
661 f
->ilf_fields
, f
->ilf_dsize
);
662 printf(" blkno: %lld len: %d boff: %d\n",
663 (long long)f
->ilf_blkno
, f
->ilf_len
, f
->ilf_boffset
);
665 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
666 printf("INODE: #regs: %d Not printing rest of data\n",
672 if (*i
>= num_ops
) /* end of LR */
673 return f
->ilf_size
-1;
675 /* core inode comes 2nd */
676 op_head
= (xlog_op_header_t
*)*ptr
;
677 xlog_print_op_header(op_head
, *i
, ptr
);
679 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
680 return f
->ilf_size
-1;
683 bcopy(*ptr
, &dino
, sizeof(dino
));
684 mode
= dino
.di_mode
& IFMT
;
685 size
= (int)dino
.di_size
;
686 xlog_print_trans_inode_core(&dino
);
687 *ptr
+= sizeof(xfs_dinode_core_t
);
689 if (*i
== num_ops
-1 && f
->ilf_size
== 3) {
693 /* does anything come next */
694 op_head
= (xlog_op_header_t
*)*ptr
;
695 switch (f
->ilf_fields
& XFS_ILOG_NONCORE
) {
696 case XFS_ILOG_DEXT
: {
697 ASSERT(f
->ilf_size
== 3);
699 xlog_print_op_header(op_head
, *i
, ptr
);
700 printf("EXTENTS inode data\n");
701 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
702 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
707 case XFS_ILOG_DBROOT
: {
708 ASSERT(f
->ilf_size
== 3);
710 xlog_print_op_header(op_head
, *i
, ptr
);
711 printf("BTREE inode data\n");
712 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
713 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
718 case XFS_ILOG_DDATA
: {
719 ASSERT(f
->ilf_size
== 3);
721 xlog_print_op_header(op_head
, *i
, ptr
);
722 printf("LOCAL inode data\n");
724 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
726 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
727 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
732 case XFS_ILOG_AEXT
: {
733 ASSERT(f
->ilf_size
== 3);
735 xlog_print_op_header(op_head
, *i
, ptr
);
736 printf("EXTENTS inode attr\n");
737 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
738 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
743 case XFS_ILOG_ABROOT
: {
744 ASSERT(f
->ilf_size
== 3);
746 xlog_print_op_header(op_head
, *i
, ptr
);
747 printf("BTREE inode attr\n");
748 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
749 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
754 case XFS_ILOG_ADATA
: {
755 ASSERT(f
->ilf_size
== 3);
757 xlog_print_op_header(op_head
, *i
, ptr
);
758 printf("LOCAL inode attr\n");
760 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
762 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
763 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
769 ASSERT(f
->ilf_size
== 2);
770 printf("DEV inode: no extra region\n");
773 case XFS_ILOG_UUID
: {
774 ASSERT(f
->ilf_size
== 2);
775 printf("UUID inode: no extra region\n");
779 ASSERT(f
->ilf_size
== 2);
783 xlog_panic("xlog_print_trans_inode: illegal inode type");
787 } /* xlog_print_trans_inode */
791 xlog_print_trans_dquot(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
793 xfs_dq_logformat_t
*f
;
794 xfs_dq_logformat_t lbuf
= {0};
795 xfs_disk_dquot_t ddq
;
796 xlog_op_header_t
*head
= NULL
;
800 * print dquot header region
802 * bcopy to ensure 8-byte alignment for the long longs in
803 * xfs_dq_logformat_t structure
805 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_dq_logformat_t
), len
));
807 (*i
)++; /* bump index */
810 if (len
== sizeof(xfs_dq_logformat_t
)) {
811 printf("#regs: %d id: 0x%x", f
->qlf_size
, f
->qlf_id
);
812 printf(" blkno: %lld len: %d boff: %d\n",
813 (long long)f
->qlf_blkno
, f
->qlf_len
, f
->qlf_boffset
);
815 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
816 printf("DQUOT: #regs: %d Not printing rest of data\n",
822 /* Check if all regions in this log item were in the given LR ptr */
823 if (*i
+num
> num_ops
-1) {
824 skip
= num
- (num_ops
-1-*i
);
831 head
= (xlog_op_header_t
*)*ptr
;
832 xlog_print_op_header(head
, *i
, ptr
);
833 ASSERT(INT_GET(head
->oh_len
, ARCH_CONVERT
) == sizeof(xfs_disk_dquot_t
));
834 bcopy(*ptr
, &ddq
, sizeof(xfs_disk_dquot_t
));
835 printf("DQUOT: magic 0x%hx flags 0%ho\n",
836 INT_GET(ddq
.d_magic
, ARCH_CONVERT
),
837 INT_GET(ddq
.d_flags
, ARCH_CONVERT
));
838 *ptr
+= INT_GET(head
->oh_len
, ARCH_CONVERT
);
840 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
843 } /* xlog_print_trans_dquot */
846 /******************************************************************************
850 ******************************************************************************
854 xlog_print_lseek(xlog_t
*log
, int fd
, xfs_daddr_t blkno
, int whence
)
856 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
859 if (whence
== SEEK_SET
)
860 offset
= BBTOOFF64(blkno
+log
->l_logBBstart
);
862 offset
= BBTOOFF64(blkno
);
863 if (lseek64(fd
, offset
, whence
) < 0) {
864 fprintf(stderr
, "%s: lseek64 to %llu failed: %s\n",
865 progname
, (unsigned long long)offset
, strerror(errno
));
868 } /* xlog_print_lseek */
872 print_lsn(xfs_caddr_t string
,
876 printf("%s: %u,%u", string
,
877 CYCLE_LSN(*lsn
, arch
), BLOCK_LSN(*lsn
, arch
));
882 xlog_print_record(int fd
,
886 xfs_caddr_t
*partial_buf
,
887 xlog_rec_header_t
*rhead
)
889 xlog_op_header_t
*op_head
;
890 xlog_rec_header_t
*rechead
;
891 xfs_caddr_t buf
, ptr
;
903 /* read_len must read up to some block boundary */
904 read_len
= (int) BBTOB(BTOBB(len
));
906 /* read_type => don't malloc() new buffer, use old one */
907 if (*read_type
== FULL_READ
) {
908 if ((ptr
= buf
= (xfs_caddr_t
)malloc(read_len
)) == NULL
) {
909 fprintf(stderr
, "xlog_print_record: malloc failed\n");
913 read_len
-= *read_type
;
914 buf
= (xfs_caddr_t
)((__psint_t
)(*partial_buf
) + (__psint_t
)(*read_type
));
917 if ((ret
= (int) read(fd
, buf
, read_len
)) == -1) {
918 fprintf(stderr
, "xlog_print_record: read error\n");
921 /* Did we overflow the end? */
922 if (*read_type
== FULL_READ
&&
923 BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)+BTOBB(read_len
) >= logBBsize
) {
924 *read_type
= BBTOB(logBBsize
-BLOCK_LSN(rhead
->h_lsn
, ARCH_CONVERT
)-1);
929 /* Did we read everything? */
930 if ((ret
== 0 && read_len
!= 0) || ret
!= read_len
) {
935 if (*read_type
!= FULL_READ
)
936 read_len
+= *read_type
;
938 /* Everything read in. Start from beginning of buffer */
940 for (i
= 0; ptr
< buf
+ read_len
; ptr
+= BBSIZE
, i
++) {
941 rechead
= (xlog_rec_header_t
*)ptr
;
942 if (INT_GET(rechead
->h_magicno
, ARCH_CONVERT
) == XLOG_HEADER_MAGIC_NUM
) {
943 xlog_print_lseek(0, fd
, -read_len
+i
*BBSIZE
, SEEK_CUR
);
947 if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) !=
948 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
)) {
949 if (*read_type
== FULL_READ
)
951 else if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) + 1 !=
952 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
))
956 INT_SET(*(uint
*)ptr
, ARCH_CONVERT
,
957 INT_GET(rhead
->h_cycle_data
[i
], ARCH_CONVERT
));
960 for (i
=0; i
<num_ops
; i
++) {
961 print_xlog_op_line();
962 op_head
= (xlog_op_header_t
*)ptr
;
963 xlog_print_op_header(op_head
, i
, &ptr
);
965 /* print transaction data */
967 ((XLOG_SET(op_head
->oh_flags
, XLOG_WAS_CONT_TRANS
) ||
968 XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) &&
969 INT_GET(op_head
->oh_len
, ARCH_CONVERT
) == 0)) {
970 for (n
= 0; n
< INT_GET(op_head
->oh_len
, ARCH_CONVERT
); n
++) {
977 if (xlog_print_find_tid(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
),
978 op_head
->oh_flags
& XLOG_WAS_CONT_TRANS
)) {
979 printf("Left over region from split log item\n");
980 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
983 if (INT_GET(op_head
->oh_len
, ARCH_CONVERT
) != 0) {
984 if (*(uint
*)ptr
== XFS_TRANS_HEADER_MAGIC
) {
985 skip
= xlog_print_trans_header(&ptr
,
986 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
988 switch (*(unsigned short *)ptr
) {
992 skip
= xlog_print_trans_buffer(&ptr
,
993 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
997 case XFS_LI_5_3_INODE
:
998 case XFS_LI_6_1_INODE
:
1000 skip
= xlog_print_trans_inode(&ptr
,
1001 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
1005 case XFS_LI_DQUOT
: {
1006 skip
= xlog_print_trans_dquot(&ptr
,
1007 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
1012 skip
= xlog_print_trans_efi(&ptr
,
1013 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1017 skip
= xlog_print_trans_efd(&ptr
,
1018 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1021 case XFS_LI_QUOTAOFF
: {
1022 skip
= xlog_print_trans_qoff(&ptr
,
1023 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1026 case XLOG_UNMOUNT_TYPE
: {
1027 printf("Unmount filesystem\n");
1032 fprintf(stderr
, "%s: unknown log operation type (%x)\n",
1033 progname
, *(unsigned short *)ptr
);
1035 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
1040 xlog_print_add_to_trans(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
), skip
);
1046 } /* xlog_print_record */
1050 xlog_print_rec_head(xlog_rec_header_t
*head
, int *len
)
1057 return INT_GET(head
->h_num_logops
, ARCH_CONVERT
);
1059 if (INT_ISZERO(head
->h_magicno
, ARCH_CONVERT
))
1062 if (INT_GET(head
->h_magicno
, ARCH_CONVERT
) != XLOG_HEADER_MAGIC_NUM
) {
1063 printf("Header 0x%x wanted 0x%x\n",
1064 INT_GET(head
->h_magicno
, ARCH_CONVERT
),
1065 XLOG_HEADER_MAGIC_NUM
);
1069 datalen
=INT_GET(head
->h_len
, ARCH_CONVERT
);
1070 bbs
=(datalen
/BBSIZE
)+(datalen
%BBSIZE
)?1:0;
1072 printf("cycle: %d version: %d ",
1073 INT_GET(head
->h_cycle
, ARCH_CONVERT
),
1074 INT_GET(head
->h_version
, ARCH_CONVERT
));
1075 print_lsn(" lsn", &head
->h_lsn
, ARCH_CONVERT
);
1076 print_lsn(" tail_lsn", &head
->h_tail_lsn
, ARCH_CONVERT
);
1078 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
1080 INT_GET(head
->h_prev_block
, ARCH_CONVERT
),
1081 INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
1083 if (print_overwrite
) {
1084 printf("cycle num overwrites: ");
1085 for (i
=0; i
< bbs
; i
++)
1086 printf("%d - 0x%x ",
1088 INT_GET(head
->h_cycle_data
[i
], ARCH_CONVERT
));
1092 uuid_unparse(head
->h_fs_uuid
, uub
);
1093 printf("uuid: %s format: ", uub
);
1094 switch (INT_GET(head
->h_fmt
, ARCH_CONVERT
)) {
1095 case XLOG_FMT_UNKNOWN
:
1096 printf("unknown\n");
1098 case XLOG_FMT_LINUX_LE
:
1099 printf("little endian linux\n");
1101 case XLOG_FMT_LINUX_BE
:
1102 printf("big endian linux\n");
1104 case XLOG_FMT_IRIX_BE
:
1105 printf("big endian irix\n");
1108 printf("? (%d)\n", INT_GET(head
->h_fmt
, ARCH_CONVERT
));
1112 *len
= INT_GET(head
->h_len
, ARCH_CONVERT
);
1113 return(INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
1114 } /* xlog_print_rec_head */
1117 print_xlog_bad_zeroed(xfs_daddr_t blkno
)
1120 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
1124 xlog_exit("Bad log - data after zeroed blocks");
1125 } /* print_xlog_bad_zeroed */
1128 print_xlog_bad_header(xfs_daddr_t blkno
, xfs_caddr_t buf
)
1131 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
1132 GET_CYCLE(buf
, ARCH_CONVERT
), (long long)blkno
);
1135 xlog_exit("Bad log record header");
1136 } /* print_xlog_bad_header */
1139 print_xlog_bad_data(xfs_daddr_t blkno
)
1142 printf("* ERROR: data block=%-21lld *\n",
1146 xlog_exit("Bad data in log");
1147 } /* print_xlog_bad_data */
1151 * This code is gross and needs to be rewritten.
1153 void xfs_log_print(xlog_t
*log
,
1155 int print_block_start
)
1157 char hbuf
[XLOG_HEADER_SIZE
];
1159 xfs_daddr_t block_end
= 0, block_start
, blkno
, error
;
1160 int read_type
= FULL_READ
;
1161 xfs_caddr_t partial_buf
;
1164 logBBsize
= log
->l_logBBsize
;
1167 * Normally, block_start and block_end are the same value since we
1168 * are printing the entire log. However, if the start block is given,
1169 * we still end at the end of the logical log.
1171 if ((error
= xlog_print_find_oldest(log
, &block_end
))) {
1172 fprintf(stderr
, "%s: problem finding oldest LR\n", progname
);
1175 if (print_block_start
== -1)
1176 block_start
= block_end
;
1178 block_start
= print_block_start
;
1179 xlog_print_lseek(log
, fd
, block_start
, SEEK_SET
);
1180 blkno
= block_start
;
1183 if (read(fd
, hbuf
, 512) == 0) {
1184 printf("%s: physical end of log\n", progname
);
1185 print_xlog_record_line();
1188 if (print_only_data
) {
1189 printf("BLKNO: %lld\n", (long long)blkno
);
1190 xlog_recover_print_data(hbuf
, 512);
1194 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1197 if (zeroed
&& num_ops
!= ZEROED_LOG
) {
1198 printf("%s: after %d zeroed blocks\n", progname
, zeroed
);
1199 /* once we find zeroed blocks - that's all we expect */
1200 print_xlog_bad_zeroed(blkno
-1);
1201 /* reset count since we're assuming previous zeroed blocks
1207 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1208 if (num_ops
== ZEROED_LOG
) {
1211 print_xlog_bad_header(blkno
-1, hbuf
);
1217 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
, &partial_buf
,
1218 (xlog_rec_header_t
*)hbuf
);
1221 blkno
+= BTOBB(len
);
1222 if (print_block_start
!= -1 &&
1223 blkno
>= block_end
) /* If start specified, we */
1224 goto end
; /* end early */
1228 print_xlog_bad_data(blkno
-1);
1229 if (print_block_start
!= -1 &&
1230 blkno
>= block_end
) /* If start specified, */
1231 goto end
; /* we end early */
1232 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1235 case PARTIAL_READ
: {
1236 print_xlog_record_line();
1237 printf("%s: physical end of log\n", progname
);
1238 print_xlog_record_line();
1240 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1242 * We may have hit the end of the log when we started at 0.
1243 * In this case, just end.
1245 if (block_start
== 0)
1247 goto partial_log_read
;
1249 default: xlog_panic("illegal value");
1251 print_xlog_record_line();
1253 if (blkno
>= logBBsize
) {
1255 printf("%s: skipped %d zeroed blocks\n", progname
, zeroed
);
1256 if (zeroed
== logBBsize
)
1257 printf("%s: totally zeroed log\n", progname
);
1261 printf("%s: physical end of log\n", progname
);
1262 print_xlog_record_line();
1267 /* Do we need to print the first part of physical log? */
1268 if (block_start
!= 0) {
1270 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1272 if (read(fd
, hbuf
, 512) == 0) {
1273 xlog_panic("xlog_find_head: bad read");
1275 if (print_only_data
) {
1276 printf("BLKNO: %lld\n", (long long)blkno
);
1277 xlog_recover_print_data(hbuf
, 512);
1281 num_ops
= xlog_print_rec_head((xlog_rec_header_t
*)hbuf
, &len
);
1284 if (num_ops
== ZEROED_LOG
|| num_ops
== BAD_HEADER
) {
1285 /* we only expect zeroed log entries at the end
1286 * of the _physical_ log, so treat them the same
1287 * as bad blocks here
1289 print_xlog_bad_header(blkno
-1, hbuf
);
1291 if (blkno
>= block_end
)
1296 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
,
1297 &partial_buf
, (xlog_rec_header_t
*)hbuf
);
1298 if (read_type
!= FULL_READ
)
1300 read_type
= FULL_READ
;
1302 blkno
+= BTOBB(len
);
1304 print_xlog_bad_data(blkno
-1);
1305 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1308 print_xlog_record_line();
1310 if (blkno
>= block_end
)
1316 printf("%s: logical end of log\n", progname
);
1317 print_xlog_record_line();