2 * Copyright (c) 2000-2003 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 CLEARED_BLKS (-5)
36 #define ZEROED_LOG (-4)
37 #define FULL_READ (-3)
38 #define PARTIAL_READ (-2)
39 #define BAD_HEADER (-1)
43 char *trans_type
[] = {
88 typedef struct xlog_split_item
{
89 struct xlog_split_item
*si_next
;
90 struct xlog_split_item
*si_prev
;
95 xlog_split_item_t
*split_list
= 0;
98 print_xlog_op_line(void)
100 printf("--------------------------------------"
101 "--------------------------------------\n");
102 } /* print_xlog_op_line */
105 print_xlog_xhdr_line(void)
107 printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
108 "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
109 } /* print_xlog_xhdr_line */
112 print_xlog_record_line(void)
114 printf("======================================"
115 "======================================\n");
116 } /* print_xlog_record_line */
121 printf("***********************************"
122 "***********************************\n");
126 * Given a pointer to a data segment, print out the data as if it were
127 * a log operation header.
130 xlog_print_op_header(xlog_op_header_t
*op_head
,
134 xlog_op_header_t hbuf
;
137 * bcopy because on 64/n32, partial reads can cause the op_head
138 * pointer to come in pointing to an odd-numbered byte
140 bcopy(op_head
, &hbuf
, sizeof(xlog_op_header_t
));
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")));
149 if (op_head
->oh_flags
) {
150 if (op_head
->oh_flags
& XLOG_START_TRANS
)
152 if (op_head
->oh_flags
& XLOG_COMMIT_TRANS
)
154 if (op_head
->oh_flags
& XLOG_WAS_CONT_TRANS
)
156 if (op_head
->oh_flags
& XLOG_UNMOUNT_TRANS
)
158 if (op_head
->oh_flags
& XLOG_CONTINUE_TRANS
)
160 if (op_head
->oh_flags
& XLOG_END_TRANS
)
166 } /* xlog_print_op_header */
170 xlog_print_add_to_trans(xlog_tid_t tid
,
173 xlog_split_item_t
*item
;
175 item
= (xlog_split_item_t
*)calloc(sizeof(xlog_split_item_t
), 1);
177 item
->si_skip
= skip
;
178 item
->si_next
= split_list
;
181 split_list
->si_prev
= item
;
183 } /* xlog_print_add_to_trans */
187 xlog_print_find_tid(xlog_tid_t tid
, uint was_cont
)
189 xlog_split_item_t
*listp
= split_list
;
192 if (was_cont
!= 0) /* Not first time we have used this tid */
198 if (listp
->si_tid
== tid
)
200 listp
= listp
->si_next
;
205 if (--listp
->si_skip
== 0) {
206 if (listp
== split_list
) { /* delete at head */
207 split_list
= listp
->si_next
;
209 split_list
->si_prev
= NULL
;
212 listp
->si_next
->si_prev
= listp
->si_prev
;
213 listp
->si_prev
->si_next
= listp
->si_next
;
218 } /* xlog_print_find_tid */
221 xlog_print_trans_header(xfs_caddr_t
*ptr
, int len
)
223 xfs_trans_header_t
*h
;
224 xfs_caddr_t cptr
= *ptr
;
226 char *magic_c
= (char *)&magic
;
230 magic
=*(__uint32_t
*)cptr
; /* XXX INT_GET soon */
233 #if __BYTE_ORDER == __LITTLE_ENDIAN
235 magic_c
[3], magic_c
[2], magic_c
[1], magic_c
[0]);
238 magic_c
[0], magic_c
[1], magic_c
[2], magic_c
[3]);
241 if (len
!= sizeof(xfs_trans_header_t
)) {
242 printf(" Not enough data to decode further\n");
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
);
249 } /* xlog_print_trans_header */
253 xlog_print_trans_buffer(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
255 xfs_buf_log_format_t
*f
;
256 xfs_buf_log_format_v1_t
*old_f
;
259 xfs_disk_dquot_t
*dq
;
260 xlog_op_header_t
*head
= 0;
263 int bucket
, col
, buckets
;
265 xfs_buf_log_format_t lbuf
;
266 int size
, blen
, map_size
, struct_size
;
270 * bcopy to ensure 8-byte alignment for the long longs in
271 * buf_log_format_t structure
273 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_buf_log_format_t
), len
));
277 if (f
->blf_type
== XFS_LI_BUF
) {
278 blkno
= f
->blf_blkno
;
281 map_size
= f
->blf_map_size
;
282 struct_size
= sizeof(xfs_buf_log_format_t
);
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
);
291 switch (f
->blf_type
) {
302 printf("UNKNOWN BUF: ");
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",
308 size
, (long long)blkno
, (unsigned long long)blkno
, blen
, map_size
);
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
);
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
);
327 head
= (xlog_op_header_t
*)*ptr
;
328 xlog_print_op_header(head
, *i
, ptr
);
330 printf("SUPER BLOCK Buffer: ");
331 if (INT_GET(head
->oh_len
, ARCH_CONVERT
) < 4*8) {
332 printf("Out of space\n");
336 * bcopy because *ptr may not be 8-byte aligned
338 bcopy(*ptr
, &x
, sizeof(long long));
339 bcopy(*ptr
+8, &y
, sizeof(long long));
340 printf("icount: %lld ifree: %lld ",
341 INT_GET(x
, ARCH_CONVERT
),
342 INT_GET(y
, ARCH_CONVERT
));
343 bcopy(*ptr
+16, &x
, sizeof(long long));
344 bcopy(*ptr
+24, &y
, sizeof(long long));
345 printf("fdblks: %lld frext: %lld\n",
346 INT_GET(x
, ARCH_CONVERT
),
347 INT_GET(y
, ARCH_CONVERT
));
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
) <
355 XFS_AGI_UNLINKED_BUCKETS
*sizeof(xfs_agino_t
)) {
356 printf("out of space\n");
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) {
372 } else if (INT_GET(head
->oh_len
, ARCH_CONVERT
) == 256) {
375 if (head
->oh_flags
& XLOG_CONTINUE_TRANS
) {
376 printf("AGI unlinked data skipped ");
377 printf("(CONTINUE set, no space)\n");
380 buckets
= XFS_AGI_UNLINKED_BUCKETS
;
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
) {
387 INT_GET(agi
->agi_unlinked
[bucket
], ARCH_CONVERT
));
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");
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
],
407 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNTi
],
409 printf("level BNO: %d CNT: %d\n",
410 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNOi
],
412 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNTi
],
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
));
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");
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",
437 INT_GET(dq
->d_blk_hardlimit
, ARCH_CONVERT
),
439 INT_GET(dq
->d_blk_softlimit
, ARCH_CONVERT
));
440 printf("blk count: %llu warns: %d timer: %d\n",
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",
447 INT_GET(dq
->d_ino_hardlimit
, ARCH_CONVERT
),
449 INT_GET(dq
->d_ino_softlimit
, ARCH_CONVERT
));
450 printf("ino count: %llu warns: %d timer: %d\n",
452 INT_GET(dq
->d_icount
, ARCH_CONVERT
),
453 INT_GET(dq
->d_iwarns
, ARCH_CONVERT
),
454 INT_GET(dq
->d_itimer
, ARCH_CONVERT
));
457 printf("BUF DATA\n");
459 uint
*dp
= (uint
*)*ptr
;
460 int nums
= INT_GET(head
->oh_len
, ARCH_CONVERT
) >> 2;
475 *ptr
+= INT_GET(head
->oh_len
, ARCH_CONVERT
);
477 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
480 } /* xlog_print_trans_buffer */
484 xlog_print_trans_efd(xfs_caddr_t
*ptr
, uint len
)
486 xfs_efd_log_format_t
*f
;
489 xfs_efd_log_format_t lbuf
;
492 * bcopy to ensure 8-byte alignment for the long longs in
493 * xfs_efd_log_format_t structure
495 bcopy(*ptr
, &lbuf
, sizeof(xfs_efd_log_format_t
));
498 if (len
>= sizeof(xfs_efd_log_format_t
)) {
499 printf("EFD: #regs: %d num_extents: %d id: 0x%llx\n",
500 f
->efd_size
, f
->efd_nextents
, (unsigned long long)f
->efd_efi_id
);
502 for (i
=0; i
< f
->efd_size
; i
++) {
503 printf("(s: 0x%llx, l: %d) ",
504 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
505 if (i
% 4 == 3) printf("\n");
508 if (i
% 4 != 0) printf("\n");
511 printf("EFD: Not enough data to decode further\n");
514 } /* xlog_print_trans_efd */
518 xlog_print_trans_efi(xfs_caddr_t
*ptr
, uint len
)
520 xfs_efi_log_format_t
*f
;
523 xfs_efi_log_format_t lbuf
;
526 * bcopy to ensure 8-byte alignment for the long longs in
527 * xfs_efi_log_format_t structure
529 bcopy(*ptr
, &lbuf
, sizeof(xfs_efi_log_format_t
));
532 if (len
>= sizeof(xfs_efi_log_format_t
)) {
533 printf("EFI: #regs: %d num_extents: %d id: 0x%llx\n",
534 f
->efi_size
, f
->efi_nextents
, (unsigned long long)f
->efi_id
);
536 for (i
=0; i
< f
->efi_size
; i
++) {
537 printf("(s: 0x%llx, l: %d) ",
538 (unsigned long long)ex
->ext_start
, ex
->ext_len
);
539 if (i
% 4 == 3) printf("\n");
542 if (i
% 4 != 0) printf("\n");
545 printf("EFI: Not enough data to decode further\n");
548 } /* xlog_print_trans_efi */
552 xlog_print_trans_qoff(xfs_caddr_t
*ptr
, uint len
)
554 xfs_qoff_logformat_t
*f
;
555 xfs_qoff_logformat_t lbuf
;
557 bcopy(*ptr
, &lbuf
, sizeof(xfs_qoff_logformat_t
));
560 if (len
>= sizeof(xfs_qoff_logformat_t
)) {
561 printf("QOFF: #regs: %d flags: 0x%x\n", f
->qf_size
, f
->qf_flags
);
564 printf("QOFF: Not enough data to decode further\n");
567 } /* xlog_print_trans_qoff */
571 xlog_print_trans_inode_core(xfs_dinode_core_t
*ip
)
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
,
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",
582 (unsigned long long)ip
->di_size
, (unsigned long long)ip
->di_nblocks
,
583 ip
->di_extsize
, ip
->di_nextents
);
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
,
587 printf("flags 0x%x gen 0x%x\n",
588 ip
->di_flags
, ip
->di_gen
);
592 xlog_print_dir_sf(xfs_dir_shortform_t
*sfp
, int size
)
598 xfs_dir_sf_entry_t
*sfep
;
600 /* XXX need to determine whether this is v1 or v2, then
601 print appropriate structure */
603 printf("SHORTFORM DIRECTORY size %d\n",
605 /* bail out for now */
609 printf("SHORTFORM DIRECTORY size %d count %d\n",
610 size
, sfp
->hdr
.count
);
611 bcopy(&(sfp
->hdr
.parent
), &ino
, sizeof(ino
));
612 printf(".. ino 0x%llx\n", (unsigned long long)INT_GET(ino
, ARCH_CONVERT
));
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",
621 namebuf
, (unsigned long long)ino
, sfep
->namelen
);
622 sfep
= XFS_DIR_SF_NEXTENTRY(sfep
);
627 xlog_print_trans_inode(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
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
;
634 xfs_inode_log_format_t lbuf
= {0};
639 * print inode type header region
641 * bcopy to ensure 8-byte alignment for the long longs in
642 * xfs_inode_log_format_t structure
644 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
646 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_inode_log_format_t
), len
));
647 version
= lbuf
.ilf_type
;
649 (*i
)++; /* bump index */
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",
655 old_f
->ilf_size
, (unsigned long long)old_f
->ilf_ino
,
656 old_f
->ilf_fields
, old_f
->ilf_dsize
);
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",
661 return old_f
->ilf_size
;
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",
669 f
->ilf_size
, (unsigned long long)f
->ilf_ino
,
670 f
->ilf_fields
, f
->ilf_dsize
);
671 printf(" blkno: %lld len: %d boff: %d\n",
672 (long long)f
->ilf_blkno
, f
->ilf_len
, f
->ilf_boffset
);
674 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
675 printf("INODE: #regs: %d Not printing rest of data\n",
681 if (*i
>= num_ops
) /* end of LR */
682 return f
->ilf_size
-1;
684 /* core inode comes 2nd */
685 op_head
= (xlog_op_header_t
*)*ptr
;
686 xlog_print_op_header(op_head
, *i
, ptr
);
688 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
689 return f
->ilf_size
-1;
692 bcopy(*ptr
, &dino
, sizeof(dino
));
693 mode
= dino
.di_mode
& S_IFMT
;
694 size
= (int)dino
.di_size
;
695 xlog_print_trans_inode_core(&dino
);
696 *ptr
+= sizeof(xfs_dinode_core_t
);
698 if (*i
== num_ops
-1 && f
->ilf_size
== 3) {
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);
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
)) {
716 case XFS_ILOG_DBROOT
: {
717 ASSERT(f
->ilf_size
== 3);
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
)) {
727 case XFS_ILOG_DDATA
: {
728 ASSERT(f
->ilf_size
== 3);
730 xlog_print_op_header(op_head
, *i
, ptr
);
731 printf("LOCAL inode data\n");
732 if (mode
== S_IFDIR
) {
733 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
735 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
736 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
741 case XFS_ILOG_AEXT
: {
742 ASSERT(f
->ilf_size
== 3);
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
)) {
752 case XFS_ILOG_ABROOT
: {
753 ASSERT(f
->ilf_size
== 3);
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
)) {
763 case XFS_ILOG_ADATA
: {
764 ASSERT(f
->ilf_size
== 3);
766 xlog_print_op_header(op_head
, *i
, ptr
);
767 printf("LOCAL inode attr\n");
768 if (mode
== S_IFDIR
) {
769 xlog_print_dir_sf((xfs_dir_shortform_t
*)*ptr
, size
);
771 *ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
772 if (XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) {
778 ASSERT(f
->ilf_size
== 2);
779 printf("DEV inode: no extra region\n");
782 case XFS_ILOG_UUID
: {
783 ASSERT(f
->ilf_size
== 2);
784 printf("UUID inode: no extra region\n");
788 ASSERT(f
->ilf_size
== 2);
792 xlog_panic("xlog_print_trans_inode: illegal inode type");
796 } /* xlog_print_trans_inode */
800 xlog_print_trans_dquot(xfs_caddr_t
*ptr
, int len
, int *i
, int num_ops
)
802 xfs_dq_logformat_t
*f
;
803 xfs_dq_logformat_t lbuf
= {0};
804 xfs_disk_dquot_t ddq
;
805 xlog_op_header_t
*head
= NULL
;
809 * print dquot header region
811 * bcopy to ensure 8-byte alignment for the long longs in
812 * xfs_dq_logformat_t structure
814 bcopy(*ptr
, &lbuf
, MIN(sizeof(xfs_dq_logformat_t
), len
));
816 (*i
)++; /* bump index */
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
);
824 ASSERT(len
>= 4); /* must have at least 4 bytes if != 0 */
825 printf("DQUOT: #regs: %d Not printing rest of data\n",
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
);
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
);
849 if (head
&& head
->oh_flags
& XLOG_CONTINUE_TRANS
)
852 } /* xlog_print_trans_dquot */
855 /******************************************************************************
859 ******************************************************************************
863 xlog_print_lseek(xlog_t
*log
, int fd
, xfs_daddr_t blkno
, int whence
)
865 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
868 if (whence
== SEEK_SET
)
869 offset
= BBTOOFF64(blkno
+log
->l_logBBstart
);
871 offset
= BBTOOFF64(blkno
);
872 if (lseek64(fd
, offset
, whence
) < 0) {
873 fprintf(stderr
, "%s: lseek64 to %lld failed: %s\n",
874 progname
, (long long)offset
, strerror(errno
));
877 } /* xlog_print_lseek */
881 print_lsn(xfs_caddr_t string
,
885 printf("%s: %u,%u", string
,
886 CYCLE_LSN(INT_GET(*lsn
, arch
)), BLOCK_LSN(INT_GET(*lsn
, arch
)));
891 xlog_print_record(int fd
,
895 xfs_caddr_t
*partial_buf
,
896 xlog_rec_header_t
*rhead
,
897 xlog_rec_ext_header_t
*xhdrs
)
899 xfs_caddr_t buf
, ptr
;
911 /* read_len must read up to some block boundary */
912 read_len
= (int) BBTOB(BTOBB(len
));
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
) {
917 fprintf(stderr
, "%s: xlog_print_record: malloc failed\n", progname
);
921 read_len
-= *read_type
;
922 buf
= (xfs_caddr_t
)((__psint_t
)(*partial_buf
) + (__psint_t
)(*read_type
));
925 if ((ret
= (int) read(fd
, buf
, read_len
)) == -1) {
926 fprintf(stderr
, "%s: xlog_print_record: read error\n", progname
);
929 /* Did we overflow the end? */
930 if (*read_type
== FULL_READ
&&
931 BLOCK_LSN(INT_GET(rhead
->h_lsn
, ARCH_CONVERT
)) + BTOBB(read_len
) >=
933 *read_type
= BBTOB(logBBsize
- BLOCK_LSN(INT_GET(rhead
->h_lsn
, ARCH_CONVERT
))-1);
938 /* Did we read everything? */
939 if ((ret
== 0 && read_len
!= 0) || ret
!= read_len
) {
944 if (*read_type
!= FULL_READ
)
945 read_len
+= *read_type
;
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.
953 for (i
= 0; ptr
< buf
+ read_len
; ptr
+= BBSIZE
, i
++) {
954 xlog_rec_header_t
*rechead
= (xlog_rec_header_t
*)ptr
;
957 if (INT_GET(rechead
->h_magicno
, ARCH_CONVERT
) == XLOG_HEADER_MAGIC_NUM
) {
958 /* data should not have magicno as first word
959 * as it should by cycle#
965 * FIXME: cycle+1 should be a macro pv#900369
967 if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) !=
968 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
)) {
969 if (*read_type
== FULL_READ
)
971 else if (INT_GET(rhead
->h_cycle
, ARCH_CONVERT
) + 1 !=
972 INT_GET(*(uint
*)ptr
, ARCH_CONVERT
))
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
));
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
));
995 for (i
=0; i
<num_ops
; i
++) {
996 xlog_op_header_t
*op_head
= (xlog_op_header_t
*)ptr
;
998 print_xlog_op_line();
999 xlog_print_op_header(op_head
, i
, &ptr
);
1001 /* print transaction data */
1002 if (print_no_data
||
1003 ((XLOG_SET(op_head
->oh_flags
, XLOG_WAS_CONT_TRANS
) ||
1004 XLOG_SET(op_head
->oh_flags
, XLOG_CONTINUE_TRANS
)) &&
1005 INT_GET(op_head
->oh_len
, ARCH_CONVERT
) == 0)) {
1006 for (n
= 0; n
< INT_GET(op_head
->oh_len
, ARCH_CONVERT
); n
++) {
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
);
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
));
1024 switch (*(unsigned short *)ptr
) {
1025 case XFS_LI_5_3_BUF
:
1026 case XFS_LI_6_1_BUF
:
1028 skip
= xlog_print_trans_buffer(&ptr
,
1029 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
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
),
1041 case XFS_LI_DQUOT
: {
1042 skip
= xlog_print_trans_dquot(&ptr
,
1043 INT_GET(op_head
->oh_len
, ARCH_CONVERT
),
1048 skip
= xlog_print_trans_efi(&ptr
,
1049 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1053 skip
= xlog_print_trans_efd(&ptr
,
1054 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1057 case XFS_LI_QUOTAOFF
: {
1058 skip
= xlog_print_trans_qoff(&ptr
,
1059 INT_GET(op_head
->oh_len
, ARCH_CONVERT
));
1062 case XLOG_UNMOUNT_TYPE
: {
1063 printf("Unmount filesystem\n");
1068 fprintf(stderr
, "%s: unknown log operation type (%x)\n",
1069 progname
, *(unsigned short *)ptr
);
1075 ptr
+= INT_GET(op_head
->oh_len
, ARCH_CONVERT
);
1080 xlog_print_add_to_trans(INT_GET(op_head
->oh_tid
, ARCH_CONVERT
), skip
);
1086 } /* xlog_print_record */
1090 xlog_print_rec_head(xlog_rec_header_t
*head
, int *len
)
1097 return INT_GET(head
->h_num_logops
, ARCH_CONVERT
);
1099 if (!head
->h_magicno
)
1102 if (INT_GET(head
->h_magicno
, ARCH_CONVERT
) != XLOG_HEADER_MAGIC_NUM
) {
1103 printf("Header 0x%x wanted 0x%x\n",
1104 INT_GET(head
->h_magicno
, ARCH_CONVERT
),
1105 XLOG_HEADER_MAGIC_NUM
);
1109 /* check for cleared blocks written by xlog_clear_stale_blocks() */
1110 if (!head
->h_len
&& !head
->h_chksum
&& !head
->h_prev_block
&&
1111 !head
->h_num_logops
&& !head
->h_size
)
1112 return CLEARED_BLKS
;
1114 datalen
=INT_GET(head
->h_len
, ARCH_CONVERT
);
1117 printf("cycle: %d version: %d ",
1118 INT_GET(head
->h_cycle
, ARCH_CONVERT
),
1119 INT_GET(head
->h_version
, ARCH_CONVERT
));
1120 print_lsn(" lsn", &head
->h_lsn
, ARCH_CONVERT
);
1121 print_lsn(" tail_lsn", &head
->h_tail_lsn
, ARCH_CONVERT
);
1123 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
1125 INT_GET(head
->h_prev_block
, ARCH_CONVERT
),
1126 INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
1128 if (print_overwrite
) {
1129 printf("cycle num overwrites: ");
1130 for (i
=0; i
< MIN(bbs
, XLOG_HEADER_CYCLE_SIZE
/ BBSIZE
); i
++)
1131 printf("%d - 0x%x ",
1133 INT_GET(head
->h_cycle_data
[i
], ARCH_CONVERT
));
1137 uuid_unparse(head
->h_fs_uuid
, uub
);
1138 printf("uuid: %s format: ", uub
);
1139 switch (INT_GET(head
->h_fmt
, ARCH_CONVERT
)) {
1140 case XLOG_FMT_UNKNOWN
:
1141 printf("unknown\n");
1143 case XLOG_FMT_LINUX_LE
:
1144 printf("little endian linux\n");
1146 case XLOG_FMT_LINUX_BE
:
1147 printf("big endian linux\n");
1149 case XLOG_FMT_IRIX_BE
:
1150 printf("big endian irix\n");
1153 printf("? (%d)\n", INT_GET(head
->h_fmt
, ARCH_CONVERT
));
1156 printf("h_size: %d\n", INT_GET(head
->h_size
, ARCH_CONVERT
));
1158 *len
= INT_GET(head
->h_len
, ARCH_CONVERT
);
1159 return(INT_GET(head
->h_num_logops
, ARCH_CONVERT
));
1160 } /* xlog_print_rec_head */
1163 xlog_print_rec_xhead(xlog_rec_ext_header_t
*head
, int coverage
)
1167 print_xlog_xhdr_line();
1168 printf("extended-header: cycle: %d\n", INT_GET(head
->xh_cycle
, ARCH_CONVERT
));
1170 if (print_overwrite
) {
1171 printf("cycle num overwrites: ");
1172 for (i
= 0; i
< coverage
; i
++)
1173 printf("%d - 0x%x ",
1175 INT_GET(head
->xh_cycle_data
[i
], ARCH_CONVERT
));
1178 } /* xlog_print_rec_xhead */
1181 print_xlog_bad_zeroed(xfs_daddr_t blkno
)
1184 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
1188 xlog_exit("Bad log - data after zeroed blocks");
1189 } /* print_xlog_bad_zeroed */
1192 print_xlog_bad_header(xfs_daddr_t blkno
, xfs_caddr_t buf
)
1195 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
1196 GET_CYCLE(buf
, ARCH_CONVERT
), (long long)blkno
);
1199 xlog_exit("Bad log record header");
1200 } /* print_xlog_bad_header */
1203 print_xlog_bad_data(xfs_daddr_t blkno
)
1206 printf("* ERROR: data block=%-21lld *\n",
1210 xlog_exit("Bad data in log");
1211 } /* print_xlog_bad_data */
1214 print_xlog_bad_reqd_hdrs(xfs_daddr_t blkno
, int num_reqd
, int num_hdrs
)
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
);
1223 xlog_exit("Not enough headers for data length.");
1224 } /* print_xlog_bad_reqd_hdrs */
1227 xlog_reallocate_xhdrs(int num_hdrs
, xlog_rec_ext_header_t
**ret_xhdrs
)
1229 int len
= (num_hdrs
-1) * sizeof(xlog_rec_ext_header_t
);
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
);
1238 /* for V2 logs read each extra hdr and print it out */
1240 xlog_print_extended_headers(
1244 xlog_rec_header_t
*hdr
,
1246 xlog_rec_ext_header_t
**ret_xhdrs
)
1252 char xhbuf
[XLOG_HEADER_SIZE
];
1253 xlog_rec_ext_header_t
*x
;
1255 num_required
= howmany(len
, XLOG_HEADER_CYCLE_SIZE
);
1256 num_hdrs
= INT_GET(hdr
->h_size
, ARCH_CONVERT
) / XLOG_HEADER_CYCLE_SIZE
;
1258 if (num_required
> num_hdrs
) {
1259 print_xlog_bad_reqd_hdrs((*blkno
)-1, num_required
, num_hdrs
);
1262 if (num_hdrs
== 1) {
1269 if (*ret_xhdrs
== NULL
|| num_hdrs
> *ret_num_hdrs
) {
1270 xlog_reallocate_xhdrs(num_hdrs
, ret_xhdrs
);
1273 *ret_num_hdrs
= num_hdrs
;
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 */
1284 if (print_only_data
) {
1285 printf("BLKNO: %lld\n", (long long)*blkno
);
1286 xlog_recover_print_data(xhbuf
, 512);
1289 if (i
== num_hdrs
- 1) {
1291 coverage_bb
= BTOBB(len
) %
1292 (XLOG_HEADER_CYCLE_SIZE
/ BBSIZE
);
1295 /* earliear header */
1296 coverage_bb
= XLOG_HEADER_CYCLE_SIZE
/ BBSIZE
;
1298 xlog_print_rec_xhead((xlog_rec_ext_header_t
*)xhbuf
, coverage_bb
);
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.
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
];
1317 * This code is gross and needs to be rewritten.
1319 void xfs_log_print(xlog_t
*log
,
1321 int print_block_start
)
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
;
1334 logBBsize
= log
->l_logBBsize
;
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.
1341 if ((error
= xlog_print_find_oldest(log
, &block_end
))) {
1342 fprintf(stderr
, "%s: problem finding oldest LR\n", progname
);
1345 if (print_block_start
== -1)
1346 block_start
= block_end
;
1348 block_start
= print_block_start
;
1349 xlog_print_lseek(log
, fd
, block_start
, SEEK_SET
);
1350 blkno
= block_start
;
1353 if (read(fd
, hbuf
, 512) == 0) {
1354 printf("%s: physical end of log\n", progname
);
1355 print_xlog_record_line();
1358 if (print_only_data
) {
1359 printf("BLKNO: %lld\n", (long long)blkno
);
1360 xlog_recover_print_data(hbuf
, 512);
1364 num_ops
= xlog_print_rec_head(hdr
, &len
);
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
1377 if (num_ops
== ZEROED_LOG
||
1378 num_ops
== CLEARED_BLKS
||
1379 num_ops
== BAD_HEADER
) {
1380 if (num_ops
== ZEROED_LOG
) {
1382 zeroed_blkno
= blkno
-1;
1385 else if (num_ops
== CLEARED_BLKS
) {
1387 cleared_blkno
= blkno
-1;
1390 print_xlog_bad_header(blkno
-1, hbuf
);
1396 if (INT_GET(hdr
->h_version
, ARCH_CONVERT
) == 2) {
1397 if (xlog_print_extended_headers(fd
, len
, &blkno
, hdr
, &num_hdrs
, &xhdrs
) != 0)
1401 error
= xlog_print_record(fd
, num_ops
, len
, &read_type
, &partial_buf
, hdr
, xhdrs
);
1404 blkno
+= BTOBB(len
);
1405 if (print_block_start
!= -1 &&
1406 blkno
>= block_end
) /* If start specified, we */
1407 goto end
; /* end early */
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
);
1418 case PARTIAL_READ
: {
1419 print_xlog_record_line();
1420 printf("%s: physical end of log\n", progname
);
1421 print_xlog_record_line();
1423 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1425 * We may have hit the end of the log when we started at 0.
1426 * In this case, just end.
1428 if (block_start
== 0)
1430 goto partial_log_read
;
1432 default: xlog_panic("illegal value");
1434 print_xlog_record_line();
1436 if (blkno
>= logBBsize
) {
1438 printf("%s: skipped %d cleared blocks in range: %lld - %lld\n",
1440 (long long)(cleared_blkno
),
1441 (long long)(cleared
+ cleared_blkno
- 1));
1442 if (cleared
== logBBsize
)
1443 printf("%s: totally cleared log\n", progname
);
1448 printf("%s: skipped %d zeroed blocks in range: %lld - %lld\n",
1450 (long long)(zeroed_blkno
),
1451 (long long)(zeroed
+ zeroed_blkno
- 1));
1452 if (zeroed
== logBBsize
)
1453 printf("%s: totally zeroed log\n", progname
);
1457 printf("%s: physical end of log\n", progname
);
1458 print_xlog_record_line();
1463 /* Do we need to print the first part of physical log? */
1464 if (block_start
!= 0) {
1466 xlog_print_lseek(log
, fd
, 0, SEEK_SET
);
1468 if (read(fd
, hbuf
, 512) == 0) {
1469 xlog_panic("xlog_find_head: bad read");
1471 if (print_only_data
) {
1472 printf("BLKNO: %lld\n", (long long)blkno
);
1473 xlog_recover_print_data(hbuf
, 512);
1477 num_ops
= xlog_print_rec_head(hdr
, &len
);
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
1487 print_xlog_bad_header(blkno
-1, hbuf
);
1489 if (blkno
>= block_end
)
1494 if (INT_GET(hdr
->h_version
, ARCH_CONVERT
) == 2) {
1495 if (xlog_print_extended_headers(fd
, len
, &blkno
, hdr
, &num_hdrs
, &xhdrs
) != 0)
1500 error
= xlog_print_record(fd
,
1505 (xlog_rec_header_t
*)hbuf
,
1507 if (read_type
!= FULL_READ
)
1509 read_type
= FULL_READ
;
1511 blkno
+= BTOBB(len
);
1513 print_xlog_bad_data(blkno
-1);
1514 xlog_print_lseek(log
, fd
, blkno
, SEEK_SET
);
1517 print_xlog_record_line();
1519 if (blkno
>= block_end
)
1525 printf("%s: logical end of log\n", progname
);
1526 print_xlog_record_line();