]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - logprint/log_misc.c
bump minor version number.
[thirdparty/xfsprogs-dev.git] / logprint / log_misc.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include "logprint.h"
34
35 #define ZEROED_LOG (-4)
36 #define FULL_READ (-3)
37 #define PARTIAL_READ (-2)
38 #define BAD_HEADER (-1)
39 #define NO_ERROR (0)
40
41 static int logBBsize;
42 char *trans_type[] = {
43 "",
44 "SETATTR",
45 "SETATTR_SIZE",
46 "INACTIVE",
47 "CREATE",
48 "CREATE_TRUNC",
49 "TRUNCATE_FILE",
50 "REMOVE",
51 "LINK",
52 "RENAME",
53 "MKDIR",
54 "RMDIR",
55 "SYMLINK",
56 "SET_DMATTRS",
57 "GROWFS",
58 "STRAT_WRITE",
59 "DIOSTRAT",
60 "WRITE_SYNC",
61 "WRITEID",
62 "ADDAFORK",
63 "ATTRINVAL",
64 "ATRUNCATE",
65 "ATTR_SET",
66 "ATTR_RM",
67 "ATTR_FLAG",
68 "CLEAR_AGI_BUCKET",
69 "QM_SBCHANGE",
70 "DUMMY1",
71 "DUMMY2",
72 "QM_QUOTAOFF",
73 "QM_DQALLOC",
74 "QM_SETQLIM",
75 "QM_DQCLUSTER",
76 "QM_QINOCREATE",
77 "QM_QUOTAOFF_END",
78 "SB_UNIT",
79 "FSYNC_TS",
80 "GROWFSRT_ALLOC",
81 "GROWFSRT_ZERO",
82 "GROWFSRT_FREE",
83 "SWAPEXT",
84 };
85
86 typedef struct xlog_split_item {
87 struct xlog_split_item *si_next;
88 struct xlog_split_item *si_prev;
89 xlog_tid_t si_tid;
90 int si_skip;
91 } xlog_split_item_t;
92
93 xlog_split_item_t *split_list = 0;
94
95 void
96 print_xlog_op_line(void)
97 {
98 printf("--------------------------------------"
99 "--------------------------------------\n");
100 } /* print_xlog_op_line */
101
102 void
103 print_xlog_record_line(void)
104 {
105 printf("======================================"
106 "======================================\n");
107 } /* print_xlog_record_line */
108
109 void
110 print_stars(void)
111 {
112 printf("***********************************"
113 "***********************************\n");
114 } /* print_xlog_record_line */
115
116 /*
117 * Given a pointer to a data segment, print out the data as if it were
118 * a log operation header.
119 */
120 void
121 xlog_print_op_header(xlog_op_header_t *op_head,
122 int i,
123 xfs_caddr_t *ptr)
124 {
125 xlog_op_header_t hbuf;
126
127 /*
128 * bcopy because on 64/n32, partial reads can cause the op_head
129 * pointer to come in pointing to an odd-numbered byte
130 */
131 bcopy(op_head, &hbuf, sizeof(xlog_op_header_t));
132 op_head = &hbuf;
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")));
139 printf("flags: ");
140 if (op_head->oh_flags) {
141 if (op_head->oh_flags & XLOG_START_TRANS)
142 printf("START ");
143 if (op_head->oh_flags & XLOG_COMMIT_TRANS)
144 printf("COMMIT ");
145 if (op_head->oh_flags & XLOG_WAS_CONT_TRANS)
146 printf("WAS_CONT ");
147 if (op_head->oh_flags & XLOG_UNMOUNT_TRANS)
148 printf("UNMOUNT ");
149 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
150 printf("CONTINUE ");
151 if (op_head->oh_flags & XLOG_END_TRANS)
152 printf("END ");
153 } else {
154 printf("none");
155 }
156 printf("\n");
157 } /* xlog_print_op_header */
158
159
160 void
161 xlog_print_add_to_trans(xlog_tid_t tid,
162 int skip)
163 {
164 xlog_split_item_t *item;
165
166 item = (xlog_split_item_t *)calloc(sizeof(xlog_split_item_t), 1);
167 item->si_tid = tid;
168 item->si_skip = skip;
169 item->si_next = split_list;
170 item->si_prev = 0;
171 if (split_list)
172 split_list->si_prev = item;
173 split_list = item;
174 } /* xlog_print_add_to_trans */
175
176
177 int
178 xlog_print_find_tid(xlog_tid_t tid, uint was_cont)
179 {
180 xlog_split_item_t *listp = split_list;
181
182 if (!split_list) {
183 if (was_cont != 0) /* Not first time we have used this tid */
184 return 1;
185 else
186 return 0;
187 }
188 while (listp) {
189 if (listp->si_tid == tid)
190 break;
191 listp = listp->si_next;
192 }
193 if (!listp) {
194 return 0;
195 }
196 if (--listp->si_skip == 0) {
197 if (listp == split_list) { /* delete at head */
198 split_list = listp->si_next;
199 if (split_list)
200 split_list->si_prev = NULL;
201 } else {
202 if (listp->si_next)
203 listp->si_next->si_prev = listp->si_prev;
204 listp->si_prev->si_next = listp->si_next;
205 }
206 free(listp);
207 }
208 return 1;
209 } /* xlog_print_find_tid */
210
211 int
212 xlog_print_trans_header(xfs_caddr_t *ptr, int len)
213 {
214 xfs_trans_header_t *h;
215 xfs_caddr_t cptr = *ptr;
216 __uint32_t magic;
217 char *magic_c = (char *)&magic;
218
219 *ptr += len;
220
221 magic=*(__uint32_t*)cptr; /* XXX INT_GET soon */
222
223 if (len >= 4)
224 printf("%c%c%c%c:",
225 #if __BYTE_ORDER == __LITTLE_ENDIAN
226 magic_c[3], magic_c[2], magic_c[1], magic_c[0]);
227 #else
228 magic_c[0], magic_c[1], magic_c[2], magic_c[3]);
229 #endif
230 if (len != sizeof(xfs_trans_header_t)) {
231 printf(" Not enough data to decode further\n");
232 return 1;
233 }
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);
237 return 0;
238 } /* xlog_print_trans_header */
239
240
241 int
242 xlog_print_trans_buffer(xfs_caddr_t *ptr, int len, int *i, int num_ops)
243 {
244 xfs_buf_log_format_t *f;
245 xfs_buf_log_format_v1_t *old_f;
246 xfs_agi_t *agi;
247 xfs_agf_t *agf;
248 xfs_disk_dquot_t *dq;
249 xlog_op_header_t *head = 0;
250 int num, skip;
251 int super_block = 0;
252 int bucket, col, buckets;
253 __int64_t blkno;
254 xfs_buf_log_format_t lbuf;
255 int size, blen, map_size, struct_size;
256 long long x, y;
257
258 /*
259 * bcopy to ensure 8-byte alignment for the long longs in
260 * buf_log_format_t structure
261 */
262 bcopy(*ptr, &lbuf, sizeof(xfs_buf_log_format_t));
263 f = &lbuf;
264 *ptr += len;
265
266 if (f->blf_type == XFS_LI_BUF) {
267 blkno = f->blf_blkno;
268 size = f->blf_size;
269 blen = f->blf_len;
270 map_size = f->blf_map_size;
271 struct_size = sizeof(xfs_buf_log_format_t);
272 } else {
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);
279 }
280 switch (f->blf_type) {
281 case XFS_LI_BUF:
282 printf("BUF: ");
283 break;
284 case XFS_LI_6_1_BUF:
285 printf("6.1 BUF: ");
286 break;
287 case XFS_LI_5_3_BUF:
288 printf("5.3 BUF: ");
289 break;
290 case XFS_LI_DQUOT:
291 printf("DQUOT BUF: ");
292 break;
293 default:
294 printf("UNKNOWN BUF: ");
295 break;
296 }
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);
301 if (blkno == 0)
302 super_block = 1;
303 } else {
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);
306 return size;
307 }
308 num = size-1;
309
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);
313 num = num_ops-1-*i;
314 } else {
315 skip = 0;
316 }
317 while (num-- > 0) {
318 (*i)++;
319 head = (xlog_op_header_t *)*ptr;
320 xlog_print_op_header(head, *i, ptr);
321 if (super_block) {
322 printf("SUPER BLOCK Buffer: ");
323 if (INT_GET(head->oh_len, ARCH_CONVERT) < 4*8) {
324 printf("Out of space\n");
325 } else {
326 printf("\n");
327 /*
328 * bcopy because *ptr may not be 8-byte aligned
329 */
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));
340 }
341 super_block = 0;
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) <
346 sizeof(xfs_agi_t) -
347 XFS_AGI_UNLINKED_BUCKETS*sizeof(xfs_agino_t)) {
348 printf("out of space\n");
349 } else {
350 printf("\n");
351 printf("ver: %d ",
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) {
363 buckets = 17;
364 } else if (INT_GET(head->oh_len, ARCH_CONVERT) == 256) {
365 buckets = 32 + 17;
366 } else {
367 buckets = XFS_AGI_UNLINKED_BUCKETS;
368 }
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) {
373 printf("0x%x ",
374 INT_GET(agi->agi_unlinked[bucket], ARCH_CONVERT));
375 }
376 }
377 printf("\n");
378 }
379 }
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");
385 } else {
386 printf("\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],
393 ARCH_CONVERT),
394 INT_GET(agf->agf_roots[XFS_BTNUM_CNTi],
395 ARCH_CONVERT));
396 printf("level BNO: %d CNT: %d\n",
397 INT_GET(agf->agf_levels[XFS_BTNUM_BNOi],
398 ARCH_CONVERT),
399 INT_GET(agf->agf_levels[XFS_BTNUM_CNTi],
400 ARCH_CONVERT));
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));
408 }
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");
415 }
416 else {
417 printf("\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 (unsigned long long)
424 INT_GET(dq->d_blk_hardlimit, ARCH_CONVERT),
425 (unsigned long long)
426 INT_GET(dq->d_blk_softlimit, ARCH_CONVERT));
427 printf("blk count: %llu warns: %d timer: %d\n",
428 (unsigned long long)
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",
433 (unsigned long long)
434 INT_GET(dq->d_ino_hardlimit, ARCH_CONVERT),
435 (unsigned long long)
436 INT_GET(dq->d_ino_softlimit, ARCH_CONVERT));
437 printf("ino count: %llu warns: %d timer: %d\n",
438 (unsigned long long)
439 INT_GET(dq->d_icount, ARCH_CONVERT),
440 INT_GET(dq->d_iwarns, ARCH_CONVERT),
441 INT_GET(dq->d_itimer, ARCH_CONVERT));
442 }
443 } else {
444 printf("BUF DATA\n");
445 if (print_data) {
446 uint *dp = (uint *)*ptr;
447 int nums = INT_GET(head->oh_len, ARCH_CONVERT) >> 2;
448 int i = 0;
449
450 while (i < nums) {
451 if ((i % 8) == 0)
452 printf("%2x ", i);
453 printf("%8x ", *dp);
454 dp++;
455 i++;
456 if ((i % 8) == 0)
457 printf("\n");
458 }
459 printf("\n");
460 }
461 }
462 *ptr += INT_GET(head->oh_len, ARCH_CONVERT);
463 }
464 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
465 skip++;
466 return skip;
467 } /* xlog_print_trans_buffer */
468
469
470 int
471 xlog_print_trans_efd(xfs_caddr_t *ptr, uint len)
472 {
473 xfs_efd_log_format_t *f;
474 xfs_extent_t *ex;
475 int i;
476 xfs_efd_log_format_t lbuf;
477
478 /*
479 * bcopy to ensure 8-byte alignment for the long longs in
480 * xfs_efd_log_format_t structure
481 */
482 bcopy(*ptr, &lbuf, sizeof(xfs_efd_log_format_t));
483 f = &lbuf;
484 *ptr += len;
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);
488 ex = f->efd_extents;
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");
493 ex++;
494 }
495 if (i % 4 != 0) printf("\n");
496 return 0;
497 } else {
498 printf("EFD: Not enough data to decode further\n");
499 return 1;
500 }
501 } /* xlog_print_trans_efd */
502
503
504 int
505 xlog_print_trans_efi(xfs_caddr_t *ptr, uint len)
506 {
507 xfs_efi_log_format_t *f;
508 xfs_extent_t *ex;
509 int i;
510 xfs_efi_log_format_t lbuf;
511
512 /*
513 * bcopy to ensure 8-byte alignment for the long longs in
514 * xfs_efi_log_format_t structure
515 */
516 bcopy(*ptr, &lbuf, sizeof(xfs_efi_log_format_t));
517 f = &lbuf;
518 *ptr += len;
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);
522 ex = f->efi_extents;
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");
527 ex++;
528 }
529 if (i % 4 != 0) printf("\n");
530 return 0;
531 } else {
532 printf("EFI: Not enough data to decode further\n");
533 return 1;
534 }
535 } /* xlog_print_trans_efi */
536
537
538 /* ARGSUSED */
539 void
540 xlog_print_trans_inode_core(xfs_dinode_core_t *ip)
541 {
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,
545 (int)ip->di_format);
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,
555 ip->di_dmstate);
556 printf("flags 0x%x gen 0x%x\n",
557 ip->di_flags, ip->di_gen);
558 }
559
560 void
561 xlog_print_dir_sf(xfs_dir_shortform_t *sfp, int size)
562 {
563 xfs_ino_t ino;
564 int count;
565 int i;
566 char namebuf[257];
567 xfs_dir_sf_entry_t *sfep;
568
569 /* XXX need to determine whether this is v1 or v2, then
570 print appropriate structure */
571
572 printf("SHORTFORM DIRECTORY size %d\n",
573 size);
574 /* bail out for now */
575
576 return;
577
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));
582
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);
592 }
593 }
594
595 int
596 xlog_print_trans_inode(xfs_caddr_t *ptr, int len, int *i, int num_ops)
597 {
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;
602 int version;
603 xfs_inode_log_format_t lbuf = {0};
604 int mode;
605 int size;
606
607 /*
608 * print inode type header region
609 *
610 * bcopy to ensure 8-byte alignment for the long longs in
611 * xfs_inode_log_format_t structure
612 *
613 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
614 */
615 bcopy(*ptr, &lbuf, MIN(sizeof(xfs_inode_log_format_t), len));
616 version = lbuf.ilf_type;
617 f = &lbuf;
618 (*i)++; /* bump index */
619 *ptr += len;
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);
626 } else {
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",
629 old_f->ilf_size);
630 return old_f->ilf_size;
631 }
632 } else {
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);
642 } else {
643 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
644 printf("INODE: #regs: %d Not printing rest of data\n",
645 f->ilf_size);
646 return f->ilf_size;
647 }
648 }
649
650 if (*i >= num_ops) /* end of LR */
651 return f->ilf_size-1;
652
653 /* core inode comes 2nd */
654 op_head = (xlog_op_header_t *)*ptr;
655 xlog_print_op_header(op_head, *i, ptr);
656
657 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
658 return f->ilf_size-1;
659 }
660
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);
666
667 if (*i == num_ops-1 && f->ilf_size == 3) {
668 return 1;
669 }
670
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);
676 (*i)++;
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)) {
681 return 1;
682 }
683 break;
684 }
685 case XFS_ILOG_DBROOT: {
686 ASSERT(f->ilf_size == 3);
687 (*i)++;
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)) {
692 return 1;
693 }
694 break;
695 }
696 case XFS_ILOG_DDATA: {
697 ASSERT(f->ilf_size == 3);
698 (*i)++;
699 xlog_print_op_header(op_head, *i, ptr);
700 printf("LOCAL inode data\n");
701 if (mode == IFDIR) {
702 xlog_print_dir_sf((xfs_dir_shortform_t*)*ptr, size);
703 }
704 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
705 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS))
706 return 1;
707 break;
708 }
709 case XFS_ILOG_DEV: {
710 ASSERT(f->ilf_size == 2);
711 printf("DEV inode: no extra region\n");
712 break;
713 }
714 case XFS_ILOG_UUID: {
715 ASSERT(f->ilf_size == 2);
716 printf("UUID inode: no extra region\n");
717 break;
718 }
719 case 0: {
720 ASSERT(f->ilf_size == 2);
721 break;
722 }
723 default: {
724 xlog_panic("xlog_print_trans_inode: illegal inode type");
725 }
726 }
727 return 0;
728 } /* xlog_print_trans_inode */
729
730
731
732 /******************************************************************************
733 *
734 * Log print routines
735 *
736 ******************************************************************************
737 */
738
739 void
740 xlog_print_lseek(xlog_t *log, int fd, xfs_daddr_t blkno, int whence)
741 {
742 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
743 xfs_off_t offset;
744
745 if (whence == SEEK_SET)
746 offset = BBTOOFF64(blkno+log->l_logBBstart);
747 else
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));
752 exit(1);
753 }
754 } /* xlog_print_lseek */
755
756
757 void
758 print_lsn(xfs_caddr_t string,
759 xfs_lsn_t *lsn,
760 xfs_arch_t arch)
761 {
762 printf("%s: %u,%u", string,
763 CYCLE_LSN(*lsn, arch), BLOCK_LSN(*lsn, arch));
764 }
765
766
767 int
768 xlog_print_record(int fd,
769 int num_ops,
770 int len,
771 int *read_type,
772 xfs_caddr_t *partial_buf,
773 xlog_rec_header_t *rhead)
774 {
775 xlog_op_header_t *op_head;
776 xlog_rec_header_t *rechead;
777 xfs_caddr_t buf, ptr;
778 int read_len, skip;
779 int ret, n, i;
780
781 if (print_no_print)
782 return NO_ERROR;
783
784 if (!len) {
785 printf("\n");
786 return NO_ERROR;
787 }
788
789 /* read_len must read up to some block boundary */
790 read_len = (int) BBTOB(BTOBB(len));
791
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");
796 exit(1);
797 }
798 } else {
799 read_len -= *read_type;
800 buf = (xfs_caddr_t)((__psint_t)(*partial_buf) + (__psint_t)(*read_type));
801 ptr = *partial_buf;
802 }
803 if ((ret = (int) read(fd, buf, read_len)) == -1) {
804 fprintf(stderr, "xlog_print_record: read error\n");
805 exit(1);
806 }
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);
811 *partial_buf = buf;
812 return PARTIAL_READ;
813 }
814
815 /* Did we read everything? */
816 if ((ret == 0 && read_len != 0) || ret != read_len) {
817 *read_type = ret;
818 *partial_buf = buf;
819 return PARTIAL_READ;
820 }
821 if (*read_type != FULL_READ)
822 read_len += *read_type;
823
824 /* Everything read in. Start from beginning of buffer */
825 buf = ptr;
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);
830 free(buf);
831 return -1;
832 } else {
833 if (INT_GET(rhead->h_cycle, ARCH_CONVERT) !=
834 INT_GET(*(uint *)ptr, ARCH_CONVERT)) {
835 if (*read_type == FULL_READ)
836 return -1;
837 else if (INT_GET(rhead->h_cycle, ARCH_CONVERT) + 1 !=
838 INT_GET(*(uint *)ptr, ARCH_CONVERT))
839 return -1;
840 }
841 }
842 INT_SET(*(uint *)ptr, ARCH_CONVERT,
843 INT_GET(rhead->h_cycle_data[i], ARCH_CONVERT));
844 }
845 ptr = buf;
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);
850
851 /* print transaction data */
852 if (print_no_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++) {
857 printf("%c", *ptr);
858 ptr++;
859 }
860 printf("\n");
861 continue;
862 }
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);
867 continue;
868 }
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));
873 } else {
874 switch (*(unsigned short *)ptr) {
875 case XFS_LI_5_3_BUF:
876 case XFS_LI_6_1_BUF:
877 case XFS_LI_DQUOT:
878 case XFS_LI_BUF: {
879 skip = xlog_print_trans_buffer(&ptr,
880 INT_GET(op_head->oh_len, ARCH_CONVERT),
881 &i, num_ops);
882 break;
883 }
884 case XFS_LI_5_3_INODE:
885 case XFS_LI_6_1_INODE:
886 case XFS_LI_INODE: {
887 skip = xlog_print_trans_inode(&ptr,
888 INT_GET(op_head->oh_len, ARCH_CONVERT),
889 &i, num_ops);
890 break;
891 }
892 case XFS_LI_EFI: {
893 skip = xlog_print_trans_efi(&ptr,
894 INT_GET(op_head->oh_len, ARCH_CONVERT));
895 break;
896 }
897 case XFS_LI_EFD: {
898 skip = xlog_print_trans_efd(&ptr,
899 INT_GET(op_head->oh_len, ARCH_CONVERT));
900 break;
901 }
902 case XLOG_UNMOUNT_TYPE: {
903 printf("Unmount filesystem\n");
904 skip = 0;
905 break;
906 }
907 default: {
908 fprintf(stderr, "%s: unknown log operation type (%x)\n",
909 progname, *(unsigned short *)ptr);
910 skip = 0;
911 ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
912 }
913 } /* switch */
914 } /* else */
915 if (skip != 0)
916 xlog_print_add_to_trans(INT_GET(op_head->oh_tid, ARCH_CONVERT), skip);
917 }
918 }
919 printf("\n");
920 free(buf);
921 return NO_ERROR;
922 } /* xlog_print_record */
923
924
925 int
926 xlog_print_rec_head(xlog_rec_header_t *head, int *len)
927 {
928 int i;
929 char uub[64];
930 int datalen,bbs;
931
932 if (print_no_print)
933 return INT_GET(head->h_num_logops, ARCH_CONVERT);
934
935 if (INT_ISZERO(head->h_magicno, ARCH_CONVERT))
936 return ZEROED_LOG;
937
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);
942 return BAD_HEADER;
943 }
944
945 datalen=INT_GET(head->h_len, ARCH_CONVERT);
946 bbs=(datalen/BBSIZE)+(datalen%BBSIZE)?1:0;
947
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);
953 printf("\n");
954 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
955 datalen,
956 INT_GET(head->h_prev_block, ARCH_CONVERT),
957 INT_GET(head->h_num_logops, ARCH_CONVERT));
958
959 if (print_overwrite) {
960 printf("cycle num overwrites: ");
961 for (i=0; i< bbs; i++)
962 printf("%d - 0x%x ",
963 i,
964 INT_GET(head->h_cycle_data[i], ARCH_CONVERT));
965 printf("\n");
966 }
967
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:
972 printf("unknown\n");
973 break;
974 case XLOG_FMT_LINUX_LE:
975 printf("little endian linux\n");
976 break;
977 case XLOG_FMT_LINUX_BE:
978 printf("big endian linux\n");
979 break;
980 case XLOG_FMT_IRIX_BE:
981 printf("big endian irix\n");
982 break;
983 default:
984 printf("? (%d)\n", INT_GET(head->h_fmt, ARCH_CONVERT));
985 break;
986 }
987
988 *len = INT_GET(head->h_len, ARCH_CONVERT);
989 return(INT_GET(head->h_num_logops, ARCH_CONVERT));
990 } /* xlog_print_rec_head */
991
992 static void
993 print_xlog_bad_zeroed(xfs_daddr_t blkno)
994 {
995 print_stars();
996 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
997 (long long)blkno);
998 print_stars();
999 if (print_exit)
1000 xlog_exit("Bad log - data after zeroed blocks");
1001 } /* print_xlog_bad_zeroed */
1002
1003 static void
1004 print_xlog_bad_header(xfs_daddr_t blkno, xfs_caddr_t buf)
1005 {
1006 print_stars();
1007 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
1008 GET_CYCLE(buf, ARCH_CONVERT), (long long)blkno);
1009 print_stars();
1010 if (print_exit)
1011 xlog_exit("Bad log record header");
1012 } /* print_xlog_bad_header */
1013
1014 void
1015 print_xlog_bad_data(xfs_daddr_t blkno)
1016 {
1017 print_stars();
1018 printf("* ERROR: data block=%-21lld *\n",
1019 (long long)blkno);
1020 print_stars();
1021 if (print_exit)
1022 xlog_exit("Bad data in log");
1023 } /* print_xlog_bad_data */
1024
1025
1026 /*
1027 * This code is gross and needs to be rewritten.
1028 */
1029 void xfs_log_print(xlog_t *log,
1030 int fd,
1031 int print_block_start)
1032 {
1033 char hbuf[XLOG_HEADER_SIZE];
1034 int num_ops, len;
1035 xfs_daddr_t block_end = 0, block_start, blkno, error;
1036 int read_type = FULL_READ;
1037 xfs_caddr_t partial_buf;
1038 int zeroed = 0;
1039
1040 logBBsize = log->l_logBBsize;
1041
1042 /*
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.
1046 */
1047 if (error = xlog_print_find_oldest(log, &block_end)) {
1048 fprintf(stderr, "%s: problem finding oldest LR\n", progname);
1049 return;
1050 }
1051 if (print_block_start == -1)
1052 block_start = block_end;
1053 else
1054 block_start = print_block_start;
1055 xlog_print_lseek(log, fd, block_start, SEEK_SET);
1056 blkno = block_start;
1057
1058 for (;;) {
1059 if (read(fd, hbuf, 512) == 0) {
1060 printf("%s: physical end of log\n", progname);
1061 print_xlog_record_line();
1062 break;
1063 }
1064 if (print_only_data) {
1065 printf("BLKNO: %lld\n", (long long)blkno);
1066 xlog_recover_print_data(hbuf, 512);
1067 blkno++;
1068 goto loop;
1069 }
1070 num_ops = xlog_print_rec_head((xlog_rec_header_t *)hbuf, &len);
1071 blkno++;
1072
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
1078 * were bad
1079 */
1080 zeroed = 0;
1081 }
1082
1083 if (num_ops == ZEROED_LOG || num_ops == BAD_HEADER) {
1084 if (num_ops == ZEROED_LOG) {
1085 zeroed++;
1086 } else {
1087 print_xlog_bad_header(blkno-1, hbuf);
1088 }
1089
1090 goto loop;
1091 }
1092
1093 error = xlog_print_record(fd, num_ops, len, &read_type, &partial_buf,
1094 (xlog_rec_header_t *)hbuf);
1095 switch (error) {
1096 case 0: {
1097 blkno += BTOBB(len);
1098 if (print_block_start != -1 &&
1099 blkno >= block_end) /* If start specified, we */
1100 goto end; /* end early */
1101 break;
1102 }
1103 case -1: {
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);
1109 goto loop;
1110 }
1111 case PARTIAL_READ: {
1112 print_xlog_record_line();
1113 printf("%s: physical end of log\n", progname);
1114 print_xlog_record_line();
1115 blkno = 0;
1116 xlog_print_lseek(log, fd, 0, SEEK_SET);
1117 /*
1118 * We may have hit the end of the log when we started at 0.
1119 * In this case, just end.
1120 */
1121 if (block_start == 0)
1122 goto end;
1123 goto partial_log_read;
1124 }
1125 default: xlog_panic("illegal value");
1126 }
1127 print_xlog_record_line();
1128 loop:
1129 if (blkno >= logBBsize) {
1130 if (zeroed) {
1131 printf("%s: skipped %d zeroed blocks\n", progname, zeroed);
1132 if (zeroed == logBBsize)
1133 printf("%s: totally zeroed log\n", progname);
1134
1135 zeroed=0;
1136 }
1137 printf("%s: physical end of log\n", progname);
1138 print_xlog_record_line();
1139 break;
1140 }
1141 }
1142
1143 /* Do we need to print the first part of physical log? */
1144 if (block_start != 0) {
1145 blkno = 0;
1146 xlog_print_lseek(log, fd, 0, SEEK_SET);
1147 for (;;) {
1148 if (read(fd, hbuf, 512) == 0) {
1149 xlog_panic("xlog_find_head: bad read");
1150 }
1151 if (print_only_data) {
1152 printf("BLKNO: %lld\n", (long long)blkno);
1153 xlog_recover_print_data(hbuf, 512);
1154 blkno++;
1155 goto loop2;
1156 }
1157 num_ops = xlog_print_rec_head((xlog_rec_header_t *)hbuf, &len);
1158 blkno++;
1159
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
1164 */
1165 print_xlog_bad_header(blkno-1, hbuf);
1166
1167 if (blkno >= block_end)
1168 break;
1169 continue;
1170 }
1171 partial_log_read:
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)
1175 len -= read_type;
1176 read_type = FULL_READ;
1177 if (!error)
1178 blkno += BTOBB(len);
1179 else {
1180 print_xlog_bad_data(blkno-1);
1181 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1182 goto loop2;
1183 }
1184 print_xlog_record_line();
1185 loop2:
1186 if (blkno >= block_end)
1187 break;
1188 }
1189 }
1190
1191 end:
1192 printf("%s: logical end of log\n", progname);
1193 print_xlog_record_line();
1194 }