]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - logprint/log_misc.c
7070fa3569550a4ad3b76d804e1a3e3a66cb96e5
[thirdparty/xfsprogs-dev.git] / logprint / log_misc.c
1 /*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "logprint.h"
20
21 #define CLEARED_BLKS (-5)
22 #define ZEROED_LOG (-4)
23 #define FULL_READ (-3)
24 #define PARTIAL_READ (-2)
25 #define BAD_HEADER (-1)
26 #define NO_ERROR (0)
27
28 static int logBBsize;
29 char *trans_type[] = {
30 "",
31 "SETATTR",
32 "SETATTR_SIZE",
33 "INACTIVE",
34 "CREATE",
35 "CREATE_TRUNC",
36 "TRUNCATE_FILE",
37 "REMOVE",
38 "LINK",
39 "RENAME",
40 "MKDIR",
41 "RMDIR",
42 "SYMLINK",
43 "SET_DMATTRS",
44 "GROWFS",
45 "STRAT_WRITE",
46 "DIOSTRAT",
47 "WRITE_SYNC",
48 "WRITEID",
49 "ADDAFORK",
50 "ATTRINVAL",
51 "ATRUNCATE",
52 "ATTR_SET",
53 "ATTR_RM",
54 "ATTR_FLAG",
55 "CLEAR_AGI_BUCKET",
56 "QM_SBCHANGE",
57 "DUMMY1",
58 "DUMMY2",
59 "QM_QUOTAOFF",
60 "QM_DQALLOC",
61 "QM_SETQLIM",
62 "QM_DQCLUSTER",
63 "QM_QINOCREATE",
64 "QM_QUOTAOFF_END",
65 "SB_UNIT",
66 "FSYNC_TS",
67 "GROWFSRT_ALLOC",
68 "GROWFSRT_ZERO",
69 "GROWFSRT_FREE",
70 "SWAPEXT",
71 "SB_COUNT",
72 "CHECKPOINT",
73 "ICREATE",
74 };
75
76 typedef struct xlog_split_item {
77 struct xlog_split_item *si_next;
78 struct xlog_split_item *si_prev;
79 xlog_tid_t si_tid;
80 int si_skip;
81 } xlog_split_item_t;
82
83 xlog_split_item_t *split_list = NULL;
84
85 void
86 print_xlog_op_line(void)
87 {
88 printf("--------------------------------------"
89 "--------------------------------------\n");
90 } /* print_xlog_op_line */
91
92 void
93 print_xlog_xhdr_line(void)
94 {
95 printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
96 "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
97 } /* print_xlog_xhdr_line */
98
99 void
100 print_xlog_record_line(void)
101 {
102 printf("======================================"
103 "======================================\n");
104 } /* print_xlog_record_line */
105
106 void
107 print_stars(void)
108 {
109 printf("***********************************"
110 "***********************************\n");
111 } /* print_stars */
112
113 /*
114 * Given a pointer to a data segment, print out the data as if it were
115 * a log operation header.
116 */
117 void
118 xlog_print_op_header(xlog_op_header_t *op_head,
119 int i,
120 xfs_caddr_t *ptr)
121 {
122 xlog_op_header_t hbuf;
123
124 /*
125 * memmove because on 64/n32, partial reads can cause the op_head
126 * pointer to come in pointing to an odd-numbered byte
127 */
128 memmove(&hbuf, op_head, sizeof(xlog_op_header_t));
129 op_head = &hbuf;
130 *ptr += sizeof(xlog_op_header_t);
131 printf(_("Oper (%d): tid: %x len: %d clientid: %s "), i,
132 be32_to_cpu(op_head->oh_tid),
133 be32_to_cpu(op_head->oh_len),
134 (op_head->oh_clientid == XFS_TRANSACTION ? "TRANS" :
135 (op_head->oh_clientid == XFS_LOG ? "LOG" : "ERROR")));
136 printf(_("flags: "));
137 if (op_head->oh_flags) {
138 if (op_head->oh_flags & XLOG_START_TRANS)
139 printf("START ");
140 if (op_head->oh_flags & XLOG_COMMIT_TRANS)
141 printf("COMMIT ");
142 if (op_head->oh_flags & XLOG_WAS_CONT_TRANS)
143 printf("WAS_CONT ");
144 if (op_head->oh_flags & XLOG_UNMOUNT_TRANS)
145 printf("UNMOUNT ");
146 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
147 printf("CONTINUE ");
148 if (op_head->oh_flags & XLOG_END_TRANS)
149 printf("END ");
150 } else {
151 printf(_("none"));
152 }
153 printf("\n");
154 } /* xlog_print_op_header */
155
156
157 void
158 xlog_print_add_to_trans(xlog_tid_t tid,
159 int skip)
160 {
161 xlog_split_item_t *item;
162
163 item = (xlog_split_item_t *)calloc(sizeof(xlog_split_item_t), 1);
164 item->si_tid = tid;
165 item->si_skip = skip;
166 item->si_next = split_list;
167 item->si_prev = NULL;
168 if (split_list)
169 split_list->si_prev = item;
170 split_list = item;
171 } /* xlog_print_add_to_trans */
172
173
174 int
175 xlog_print_find_tid(xlog_tid_t tid, uint was_cont)
176 {
177 xlog_split_item_t *listp = split_list;
178
179 if (!split_list) {
180 if (was_cont != 0) /* Not first time we have used this tid */
181 return 1;
182 else
183 return 0;
184 }
185 while (listp) {
186 if (listp->si_tid == tid)
187 break;
188 listp = listp->si_next;
189 }
190 if (!listp) {
191 return 0;
192 }
193 if (--listp->si_skip == 0) {
194 if (listp == split_list) { /* delete at head */
195 split_list = listp->si_next;
196 if (split_list)
197 split_list->si_prev = NULL;
198 } else {
199 if (listp->si_next)
200 listp->si_next->si_prev = listp->si_prev;
201 listp->si_prev->si_next = listp->si_next;
202 }
203 free(listp);
204 }
205 return 1;
206 } /* xlog_print_find_tid */
207
208 int
209 xlog_print_trans_header(xfs_caddr_t *ptr, int len)
210 {
211 xfs_trans_header_t *h;
212 xfs_caddr_t cptr = *ptr;
213 __uint32_t magic;
214 char *magic_c = (char *)&magic;
215
216 *ptr += len;
217
218 magic=*(__uint32_t*)cptr; /* XXX be32_to_cpu soon */
219
220 if (len >= 4) {
221 #if __BYTE_ORDER == __LITTLE_ENDIAN
222 printf("%c%c%c%c:",
223 magic_c[3], magic_c[2], magic_c[1], magic_c[0]);
224 #else
225 printf("%c%c%c%c:",
226 magic_c[0], magic_c[1], magic_c[2], magic_c[3]);
227 #endif
228 }
229 if (len != sizeof(xfs_trans_header_t)) {
230 printf(_(" Not enough data to decode further\n"));
231 return 1;
232 }
233 h = (xfs_trans_header_t *)cptr;
234 printf(_(" type: %s tid: %x num_items: %d\n"),
235 trans_type[h->th_type], h->th_tid, h->th_num_items);
236 return 0;
237 } /* xlog_print_trans_header */
238
239
240 int
241 xlog_print_trans_buffer(xfs_caddr_t *ptr, int len, int *i, int num_ops)
242 {
243 xfs_buf_log_format_t *f;
244 xfs_agi_t *agi;
245 xfs_agf_t *agf;
246 xfs_disk_dquot_t *dq;
247 xlog_op_header_t *head = NULL;
248 int num, skip;
249 int super_block = 0;
250 int bucket, col, buckets;
251 __int64_t blkno;
252 xfs_buf_log_format_t lbuf;
253 int size, blen, map_size, struct_size;
254 __be64 x, y;
255 ushort flags;
256
257 /*
258 * memmove to ensure 8-byte alignment for the long longs in
259 * buf_log_format_t structure
260 */
261 memmove(&lbuf, *ptr, MIN(sizeof(xfs_buf_log_format_t), len));
262 f = &lbuf;
263 *ptr += len;
264
265 ASSERT(f->blf_type == XFS_LI_BUF);
266 printf("BUF: ");
267 blkno = f->blf_blkno;
268 size = f->blf_size;
269 blen = f->blf_len;
270 map_size = f->blf_map_size;
271 flags = f->blf_flags;
272
273 /*
274 * size of the format header is dependent on the size of the bitmap, not
275 * the size of the in-memory structure. Hence the slightly obtuse
276 * calculation.
277 */
278 struct_size = offsetof(struct xfs_buf_log_format, blf_map_size) + map_size;
279
280 if (len >= struct_size) {
281 ASSERT((len - sizeof(struct_size)) % sizeof(int) == 0);
282 printf(_("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d flags: 0x%x\n"),
283 size, (long long)blkno, (unsigned long long)blkno, blen, map_size, flags);
284 if (blkno == 0)
285 super_block = 1;
286 } else {
287 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
288 printf(_("#regs: %d Not printing rest of data\n"), f->blf_size);
289 return size;
290 }
291 num = size-1;
292
293 /* Check if all regions in this log item were in the given LR ptr */
294 if (*i+num > num_ops-1) {
295 skip = num - (num_ops-1-*i);
296 num = num_ops-1-*i;
297 } else {
298 skip = 0;
299 }
300 while (num-- > 0) {
301 (*i)++;
302 head = (xlog_op_header_t *)*ptr;
303 xlog_print_op_header(head, *i, ptr);
304 if (super_block) {
305 printf(_("SUPER BLOCK Buffer: "));
306 if (be32_to_cpu(head->oh_len) < 4*8) {
307 printf(_("Out of space\n"));
308 } else {
309 printf("\n");
310 /*
311 * memmove because *ptr may not be 8-byte aligned
312 */
313 memmove(&x, *ptr, sizeof(__be64));
314 memmove(&y, *ptr+8, sizeof(__be64));
315 printf(_("icount: %llu ifree: %llu "),
316 (unsigned long long) be64_to_cpu(x),
317 (unsigned long long) be64_to_cpu(y));
318 memmove(&x, *ptr+16, sizeof(__be64));
319 memmove(&y, *ptr+24, sizeof(__be64));
320 printf(_("fdblks: %llu frext: %llu\n"),
321 (unsigned long long) be64_to_cpu(x),
322 (unsigned long long) be64_to_cpu(y));
323 }
324 super_block = 0;
325 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGI_MAGIC) {
326 agi = (xfs_agi_t *)(*ptr);
327 printf(_("AGI Buffer: XAGI "));
328 if (be32_to_cpu(head->oh_len) < sizeof(xfs_agi_t) -
329 XFS_AGI_UNLINKED_BUCKETS*sizeof(xfs_agino_t)) {
330 printf(_("out of space\n"));
331 } else {
332 printf("\n");
333 printf(_("ver: %d "),
334 be32_to_cpu(agi->agi_versionnum));
335 printf(_("seq#: %d len: %d cnt: %d root: %d\n"),
336 be32_to_cpu(agi->agi_seqno),
337 be32_to_cpu(agi->agi_length),
338 be32_to_cpu(agi->agi_count),
339 be32_to_cpu(agi->agi_root));
340 printf(_("level: %d free#: 0x%x newino: 0x%x\n"),
341 be32_to_cpu(agi->agi_level),
342 be32_to_cpu(agi->agi_freecount),
343 be32_to_cpu(agi->agi_newino));
344 if (be32_to_cpu(head->oh_len) == 128) {
345 buckets = 17;
346 } else if (be32_to_cpu(head->oh_len) == 256) {
347 buckets = 32 + 17;
348 } else {
349 if (head->oh_flags & XLOG_CONTINUE_TRANS) {
350 printf(_("AGI unlinked data skipped "));
351 printf(_("(CONTINUE set, no space)\n"));
352 continue;
353 }
354 buckets = XFS_AGI_UNLINKED_BUCKETS;
355 }
356 for (bucket = 0; bucket < buckets;) {
357 printf(_("bucket[%d - %d]: "), bucket, bucket+3);
358 for (col = 0; col < 4; col++, bucket++) {
359 if (bucket < buckets) {
360 printf("0x%x ",
361 be32_to_cpu(agi->agi_unlinked[bucket]));
362 }
363 }
364 printf("\n");
365 }
366 }
367 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_AGF_MAGIC) {
368 agf = (xfs_agf_t *)(*ptr);
369 printf(_("AGF Buffer: XAGF "));
370 if (be32_to_cpu(head->oh_len) < sizeof(xfs_agf_t)) {
371 printf(_("Out of space\n"));
372 } else {
373 printf("\n");
374 printf(_("ver: %d seq#: %d len: %d \n"),
375 be32_to_cpu(agf->agf_versionnum),
376 be32_to_cpu(agf->agf_seqno),
377 be32_to_cpu(agf->agf_length));
378 printf(_("root BNO: %d CNT: %d\n"),
379 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]),
380 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
381 printf(_("level BNO: %d CNT: %d\n"),
382 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]),
383 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
384 printf(_("1st: %d last: %d cnt: %d "
385 "freeblks: %d longest: %d\n"),
386 be32_to_cpu(agf->agf_flfirst),
387 be32_to_cpu(agf->agf_fllast),
388 be32_to_cpu(agf->agf_flcount),
389 be32_to_cpu(agf->agf_freeblks),
390 be32_to_cpu(agf->agf_longest));
391 }
392 } else if (be32_to_cpu(*(__be32 *)(*ptr)) == XFS_DQUOT_MAGIC) {
393 dq = (xfs_disk_dquot_t *)(*ptr);
394 printf(_("DQUOT Buffer: DQ "));
395 if (be32_to_cpu(head->oh_len) <
396 sizeof(xfs_disk_dquot_t)) {
397 printf(_("Out of space\n"));
398 }
399 else {
400 printf("\n");
401 printf(_("ver: %d flags: 0x%x id: %d \n"),
402 dq->d_version, dq->d_flags,
403 be32_to_cpu(dq->d_id));
404 printf(_("blk limits hard: %llu soft: %llu\n"),
405 (unsigned long long)
406 be64_to_cpu(dq->d_blk_hardlimit),
407 (unsigned long long)
408 be64_to_cpu(dq->d_blk_softlimit));
409 printf(_("blk count: %llu warns: %d timer: %d\n"),
410 (unsigned long long) be64_to_cpu(dq->d_bcount),
411 (int) be16_to_cpu(dq->d_bwarns),
412 be32_to_cpu(dq->d_btimer));
413 printf(_("ino limits hard: %llu soft: %llu\n"),
414 (unsigned long long)
415 be64_to_cpu(dq->d_ino_hardlimit),
416 (unsigned long long)
417 be64_to_cpu(dq->d_ino_softlimit));
418 printf(_("ino count: %llu warns: %d timer: %d\n"),
419 (unsigned long long) be64_to_cpu(dq->d_icount),
420 (int) be16_to_cpu(dq->d_iwarns),
421 be32_to_cpu(dq->d_itimer));
422 }
423 } else {
424 printf(_("BUF DATA\n"));
425 if (print_data) {
426 uint *dp = (uint *)*ptr;
427 int nums = be32_to_cpu(head->oh_len) >> 2;
428 int i = 0;
429
430 while (i < nums) {
431 if ((i % 8) == 0)
432 printf("%2x ", i);
433 printf("%8x ", *dp);
434 dp++;
435 i++;
436 if ((i % 8) == 0)
437 printf("\n");
438 }
439 printf("\n");
440 }
441 }
442 *ptr += be32_to_cpu(head->oh_len);
443 }
444 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
445 skip++;
446 return skip;
447 } /* xlog_print_trans_buffer */
448
449
450 int
451 xlog_print_trans_efd(xfs_caddr_t *ptr, uint len)
452 {
453 xfs_efd_log_format_t *f;
454 xfs_efd_log_format_t lbuf;
455 /* size without extents at end */
456 uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t);
457
458 /*
459 * memmove to ensure 8-byte alignment for the long longs in
460 * xfs_efd_log_format_t structure
461 */
462 memmove(&lbuf, *ptr, MIN(core_size, len));
463 f = &lbuf;
464 *ptr += len;
465 if (len >= core_size) {
466 printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"),
467 f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id);
468
469 /* don't print extents as they are not used */
470
471 return 0;
472 } else {
473 printf(_("EFD: Not enough data to decode further\n"));
474 return 1;
475 }
476 } /* xlog_print_trans_efd */
477
478
479 int
480 xlog_print_trans_efi(xfs_caddr_t *ptr, uint src_len)
481 {
482 xfs_efi_log_format_t *src_f, *f;
483 uint dst_len;
484 xfs_extent_t *ex;
485 int i;
486 int error = 0;
487
488 /*
489 * memmove to ensure 8-byte alignment for the long longs in
490 * xfs_efi_log_format_t structure
491 */
492 if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) {
493 fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname);
494 exit(1);
495 }
496 memmove((char*)src_f, *ptr, src_len);
497 *ptr += src_len;
498
499 /* convert to native format */
500 dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
501 if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) {
502 fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname);
503 exit(1);
504 }
505 if (xfs_efi_copy_format((char*)src_f, src_len, f)) {
506 error = 1;
507 goto error;
508 }
509
510 printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"),
511 f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id);
512 ex = f->efi_extents;
513 for (i=0; i < f->efi_nextents; i++) {
514 printf("(s: 0x%llx, l: %d) ",
515 (unsigned long long)ex->ext_start, ex->ext_len);
516 if (i % 4 == 3) printf("\n");
517 ex++;
518 }
519 if (i % 4 != 0) printf("\n");
520 error:
521 free(src_f);
522 free(f);
523 return error;
524 } /* xlog_print_trans_efi */
525
526
527 int
528 xlog_print_trans_qoff(xfs_caddr_t *ptr, uint len)
529 {
530 xfs_qoff_logformat_t *f;
531 xfs_qoff_logformat_t lbuf;
532
533 memmove(&lbuf, *ptr, MIN(sizeof(xfs_qoff_logformat_t), len));
534 f = &lbuf;
535 *ptr += len;
536 if (len >= sizeof(xfs_qoff_logformat_t)) {
537 printf(_("QOFF: #regs: %d flags: 0x%x\n"), f->qf_size, f->qf_flags);
538 return 0;
539 } else {
540 printf(_("QOFF: Not enough data to decode further\n"));
541 return 1;
542 }
543 } /* xlog_print_trans_qoff */
544
545
546 void
547 xlog_print_trans_inode_core(xfs_icdinode_t *ip)
548 {
549 printf(_("INODE CORE\n"));
550 printf(_("magic 0x%hx mode 0%ho version %d format %d\n"),
551 ip->di_magic, ip->di_mode, (int)ip->di_version,
552 (int)ip->di_format);
553 printf(_("nlink %hd uid %d gid %d\n"),
554 ip->di_nlink, ip->di_uid, ip->di_gid);
555 printf(_("atime 0x%x mtime 0x%x ctime 0x%x\n"),
556 ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec);
557 printf(_("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n"),
558 (unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
559 ip->di_extsize, ip->di_nextents);
560 printf(_("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n"),
561 ip->di_anextents, (int)ip->di_forkoff, ip->di_dmevmask,
562 ip->di_dmstate);
563 printf(_("flags 0x%x gen 0x%x\n"),
564 ip->di_flags, ip->di_gen);
565 }
566
567 void
568 xlog_print_dir2_sf(
569 struct xlog *log,
570 xfs_dir2_sf_hdr_t *sfp,
571 int size)
572 {
573 xfs_ino_t ino;
574 int count;
575 int i;
576 char namebuf[257];
577 xfs_dir2_sf_entry_t *sfep;
578
579 printf(_("SHORTFORM DIRECTORY size %d\n"),
580 size);
581 /* bail out for now */
582
583 return;
584
585 printf(_("SHORTFORM DIRECTORY size %d count %d\n"),
586 size, sfp->count);
587 memmove(&ino, &(sfp->parent), sizeof(ino));
588 printf(_(".. ino 0x%llx\n"), (unsigned long long) be64_to_cpu(ino));
589
590 count = sfp->count;
591 sfep = xfs_dir2_sf_firstentry(sfp);
592 for (i = 0; i < count; i++) {
593 ino = xfs_dir3_sfe_get_ino(log->l_mp, sfp, sfep);
594 memmove(namebuf, (sfep->name), sfep->namelen);
595 namebuf[sfep->namelen] = '\0';
596 printf(_("%s ino 0x%llx namelen %d\n"),
597 namebuf, (unsigned long long)ino, sfep->namelen);
598 sfep = xfs_dir3_sf_nextentry(log->l_mp, sfp, sfep);
599 }
600 }
601
602 int
603 xlog_print_trans_inode(
604 struct xlog *log,
605 xfs_caddr_t *ptr,
606 int len,
607 int *i,
608 int num_ops,
609 boolean_t continued)
610 {
611 xfs_icdinode_t dino;
612 xlog_op_header_t *op_head;
613 xfs_inode_log_format_t dst_lbuf;
614 xfs_inode_log_format_64_t src_lbuf; /* buffer of biggest one */
615 xfs_inode_log_format_t *f;
616 int mode;
617 int size;
618
619 /*
620 * print inode type header region
621 *
622 * memmove to ensure 8-byte alignment for the long longs in
623 * xfs_inode_log_format_t structure
624 *
625 * len can be smaller than xfs_inode_log_format_32|64_t
626 * if format data is split over operations
627 */
628 memmove(&src_lbuf, *ptr, MIN(sizeof(xfs_inode_log_format_64_t), len));
629 (*i)++; /* bump index */
630 *ptr += len;
631 if (!continued &&
632 (len == sizeof(xfs_inode_log_format_32_t) ||
633 len == sizeof(xfs_inode_log_format_64_t))) {
634 f = xfs_inode_item_format_convert((char*)&src_lbuf, len, &dst_lbuf);
635 printf(_("INODE: "));
636 printf(_("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n"),
637 f->ilf_size, (unsigned long long)f->ilf_ino,
638 f->ilf_fields, f->ilf_dsize);
639 printf(_(" blkno: %lld len: %d boff: %d\n"),
640 (long long)f->ilf_blkno, f->ilf_len, f->ilf_boffset);
641 } else {
642 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
643 f = (xfs_inode_log_format_t *)&src_lbuf;
644 printf(_("INODE: #regs: %d Not printing rest of data\n"),
645 f->ilf_size);
646 return f->ilf_size;
647 }
648
649 if (*i >= num_ops) /* end of LR */
650 return f->ilf_size-1;
651
652 /* core inode comes 2nd */
653 op_head = (xlog_op_header_t *)*ptr;
654 xlog_print_op_header(op_head, *i, ptr);
655
656 if (op_head->oh_flags & XLOG_CONTINUE_TRANS) {
657 return f->ilf_size-1;
658 }
659
660 memmove(&dino, *ptr, sizeof(dino));
661 mode = dino.di_mode & S_IFMT;
662 size = (int)dino.di_size;
663 xlog_print_trans_inode_core(&dino);
664 *ptr += xfs_icdinode_size(dino.di_version);
665
666 if (*i == num_ops-1 && f->ilf_size == 3) {
667 return 1;
668 }
669
670 /* does anything come next */
671 op_head = (xlog_op_header_t *)*ptr;
672
673 switch (f->ilf_fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
674 case XFS_ILOG_DEV:
675 printf(_("DEV inode: no extra region\n"));
676 break;
677 case XFS_ILOG_UUID:
678 printf(_("UUID inode: no extra region\n"));
679 break;
680 }
681
682 /* Only the inode core is logged */
683 if (f->ilf_size == 2)
684 return 0;
685
686 ASSERT(f->ilf_size <= 4);
687 ASSERT((f->ilf_size == 3) || (f->ilf_fields & XFS_ILOG_AFORK));
688
689 if (f->ilf_fields & XFS_ILOG_DFORK) {
690 (*i)++;
691 xlog_print_op_header(op_head, *i, ptr);
692
693 switch (f->ilf_fields & XFS_ILOG_DFORK) {
694 case XFS_ILOG_DEXT:
695 printf(_("EXTENTS inode data\n"));
696 break;
697 case XFS_ILOG_DBROOT:
698 printf(_("BTREE inode data\n"));
699 break;
700 case XFS_ILOG_DDATA:
701 printf(_("LOCAL inode data\n"));
702 if (mode == S_IFDIR)
703 xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size);
704 break;
705 default:
706 ASSERT((f->ilf_fields & XFS_ILOG_DFORK) == 0);
707 break;
708 }
709
710 *ptr += be32_to_cpu(op_head->oh_len);
711 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
712 return 1;
713 op_head = (xlog_op_header_t *)*ptr;
714 }
715
716 if (f->ilf_fields & XFS_ILOG_AFORK) {
717 (*i)++;
718 xlog_print_op_header(op_head, *i, ptr);
719
720 switch (f->ilf_fields & XFS_ILOG_AFORK) {
721 case XFS_ILOG_AEXT:
722 printf(_("EXTENTS attr data\n"));
723 break;
724 case XFS_ILOG_ABROOT:
725 printf(_("BTREE attr data\n"));
726 break;
727 case XFS_ILOG_ADATA:
728 printf(_("LOCAL attr data\n"));
729 if (mode == S_IFDIR)
730 xlog_print_dir2_sf(log, (xfs_dir2_sf_hdr_t *)*ptr, size);
731 break;
732 default:
733 ASSERT((f->ilf_fields & XFS_ILOG_AFORK) == 0);
734 break;
735 }
736 *ptr += be32_to_cpu(op_head->oh_len);
737 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
738 return 1;
739 op_head = (xlog_op_header_t *)*ptr;
740 }
741
742 return 0;
743 } /* xlog_print_trans_inode */
744
745
746 int
747 xlog_print_trans_dquot(xfs_caddr_t *ptr, int len, int *i, int num_ops)
748 {
749 xfs_dq_logformat_t *f;
750 xfs_dq_logformat_t lbuf = {0};
751 xfs_disk_dquot_t ddq;
752 xlog_op_header_t *head = NULL;
753 int num, skip;
754
755 /*
756 * print dquot header region
757 *
758 * memmove to ensure 8-byte alignment for the long longs in
759 * xfs_dq_logformat_t structure
760 */
761 memmove(&lbuf, *ptr, MIN(sizeof(xfs_dq_logformat_t), len));
762 f = &lbuf;
763 (*i)++; /* bump index */
764 *ptr += len;
765
766 if (len == sizeof(xfs_dq_logformat_t)) {
767 printf(_("#regs: %d id: 0x%x"), f->qlf_size, f->qlf_id);
768 printf(_(" blkno: %lld len: %d boff: %d\n"),
769 (long long)f->qlf_blkno, f->qlf_len, f->qlf_boffset);
770 } else {
771 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
772 printf(_("DQUOT: #regs: %d Not printing rest of data\n"),
773 f->qlf_size);
774 return f->qlf_size;
775 }
776 num = f->qlf_size-1;
777
778 /* Check if all regions in this log item were in the given LR ptr */
779 if (*i+num > num_ops-1) {
780 skip = num - (num_ops-1-*i);
781 num = num_ops-1-*i;
782 } else {
783 skip = 0;
784 }
785
786 while (num-- > 0) {
787 head = (xlog_op_header_t *)*ptr;
788 xlog_print_op_header(head, *i, ptr);
789 ASSERT(be32_to_cpu(head->oh_len) == sizeof(xfs_disk_dquot_t));
790 memmove(&ddq, *ptr, sizeof(xfs_disk_dquot_t));
791 printf(_("DQUOT: magic 0x%hx flags 0%ho\n"),
792 be16_to_cpu(ddq.d_magic), ddq.d_flags);
793 *ptr += be32_to_cpu(head->oh_len);
794 }
795 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
796 skip++;
797 return skip;
798 } /* xlog_print_trans_dquot */
799
800
801 STATIC int
802 xlog_print_trans_icreate(
803 xfs_caddr_t *ptr,
804 int len,
805 int *i,
806 int num_ops)
807 {
808 struct xfs_icreate_log icl_buf = {0};
809 struct xfs_icreate_log *icl;
810
811 memmove(&icl_buf, *ptr, MIN(sizeof(struct xfs_icreate_log), len));
812 icl = &icl_buf;
813 (*i)++;
814 *ptr += len;
815
816 /* handle complete header only */
817 if (len != sizeof(struct xfs_icreate_log)) {
818 printf(_("ICR: split header, not printing\n"));
819 return 1; /* to skip leftover in next region */
820 }
821
822 printf(_("ICR: #ag: %d agbno: 0x%x len: %d\n"
823 " cnt: %d isize: %d gen: 0x%x\n"),
824 be32_to_cpu(icl->icl_ag), be32_to_cpu(icl->icl_agbno),
825 be32_to_cpu(icl->icl_length), be32_to_cpu(icl->icl_count),
826 be32_to_cpu(icl->icl_isize), be32_to_cpu(icl->icl_gen));
827 return 0;
828 }
829
830 /******************************************************************************
831 *
832 * Log print routines
833 *
834 ******************************************************************************
835 */
836
837 void
838 xlog_print_lseek(struct xlog *log, int fd, xfs_daddr_t blkno, int whence)
839 {
840 #define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
841 xfs_off_t offset;
842
843 if (whence == SEEK_SET)
844 offset = BBTOOFF64(blkno+log->l_logBBstart);
845 else
846 offset = BBTOOFF64(blkno);
847 if (lseek64(fd, offset, whence) < 0) {
848 fprintf(stderr, _("%s: lseek64 to %lld failed: %s\n"),
849 progname, (long long)offset, strerror(errno));
850 exit(1);
851 }
852 } /* xlog_print_lseek */
853
854
855 void
856 print_lsn(xfs_caddr_t string,
857 __be64 *lsn)
858 {
859 printf("%s: %u,%u", string,
860 CYCLE_LSN(be64_to_cpu(*lsn)), BLOCK_LSN(be64_to_cpu(*lsn)));
861 }
862
863
864 int
865 xlog_print_record(
866 struct xlog *log,
867 int fd,
868 int num_ops,
869 int len,
870 int *read_type,
871 xfs_caddr_t *partial_buf,
872 xlog_rec_header_t *rhead,
873 xlog_rec_ext_header_t *xhdrs,
874 int bad_hdr_warn)
875 {
876 xfs_caddr_t buf, ptr;
877 int read_len, skip, lost_context = 0;
878 int ret, n, i, j, k;
879
880 if (print_no_print)
881 return NO_ERROR;
882
883 if (!len) {
884 printf("\n");
885 return NO_ERROR;
886 }
887
888 /* read_len must read up to some block boundary */
889 read_len = (int) BBTOB(BTOBB(len));
890
891 /* read_type => don't malloc() new buffer, use old one */
892 if (*read_type == FULL_READ) {
893 if ((ptr = buf = (xfs_caddr_t)malloc(read_len)) == NULL) {
894 fprintf(stderr, _("%s: xlog_print_record: malloc failed\n"), progname);
895 exit(1);
896 }
897 } else {
898 read_len -= *read_type;
899 buf = (xfs_caddr_t)((__psint_t)(*partial_buf) + (__psint_t)(*read_type));
900 ptr = *partial_buf;
901 }
902 if ((ret = (int) read(fd, buf, read_len)) == -1) {
903 fprintf(stderr, _("%s: xlog_print_record: read error\n"), progname);
904 exit(1);
905 }
906 /* Did we overflow the end? */
907 if (*read_type == FULL_READ &&
908 BLOCK_LSN(be64_to_cpu(rhead->h_lsn)) + BTOBB(read_len) >=
909 logBBsize) {
910 *read_type = BBTOB(logBBsize - BLOCK_LSN(be64_to_cpu(rhead->h_lsn))-1);
911 *partial_buf = buf;
912 return PARTIAL_READ;
913 }
914
915 /* Did we read everything? */
916 if ((ret == 0 && read_len != 0) || ret != read_len) {
917 *read_type = ret;
918 *partial_buf = buf;
919 return PARTIAL_READ;
920 }
921 if (*read_type != FULL_READ)
922 read_len += *read_type;
923
924 /* Everything read in. Start from beginning of buffer
925 * Unpack the data, by putting the saved cycle-data back
926 * into the first word of each BB.
927 * Do some checks.
928 */
929 buf = ptr;
930 for (i = 0; ptr < buf + read_len; ptr += BBSIZE, i++) {
931 xlog_rec_header_t *rechead = (xlog_rec_header_t *)ptr;
932
933 /* sanity checks */
934 if (be32_to_cpu(rechead->h_magicno) == XLOG_HEADER_MAGIC_NUM) {
935 /* data should not have magicno as first word
936 * as it should by cycle#
937 */
938 free(buf);
939 return -1;
940 } else {
941 /* verify cycle#
942 * FIXME: cycle+1 should be a macro pv#900369
943 */
944 if (be32_to_cpu(rhead->h_cycle) !=
945 be32_to_cpu(*(__be32 *)ptr)) {
946 if (*read_type == FULL_READ)
947 return -1;
948 else if (be32_to_cpu(rhead->h_cycle) + 1 !=
949 be32_to_cpu(*(__be32 *)ptr))
950 return -1;
951 }
952 }
953
954 /* copy back the data from the header */
955 if (i < XLOG_HEADER_CYCLE_SIZE / BBSIZE) {
956 /* from 1st header */
957 *(__be32 *)ptr = rhead->h_cycle_data[i];
958 }
959 else {
960 ASSERT(xhdrs != NULL);
961 /* from extra headers */
962 j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
963 k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
964 *(__be32 *)ptr = xhdrs[j-1].xh_cycle_data[k];
965 }
966
967 }
968
969 ptr = buf;
970 for (i=0; i<num_ops; i++) {
971 int continued;
972
973 xlog_op_header_t *op_head = (xlog_op_header_t *)ptr;
974
975 print_xlog_op_line();
976 xlog_print_op_header(op_head, i, &ptr);
977 continued = ((op_head->oh_flags & XLOG_WAS_CONT_TRANS) ||
978 (op_head->oh_flags & XLOG_CONTINUE_TRANS));
979
980 if (continued && be32_to_cpu(op_head->oh_len) == 0)
981 continue;
982
983 if (print_no_data) {
984 for (n = 0; n < be32_to_cpu(op_head->oh_len); n++) {
985 printf("0x%02x ", (unsigned int)*ptr);
986 if (n % 16 == 15)
987 printf("\n");
988 ptr++;
989 }
990 printf("\n");
991 continue;
992 }
993
994 /* print transaction data */
995 if (xlog_print_find_tid(be32_to_cpu(op_head->oh_tid),
996 op_head->oh_flags & XLOG_WAS_CONT_TRANS)) {
997 printf(_("Left over region from split log item\n"));
998 /* Skip this leftover bit */
999 ptr += be32_to_cpu(op_head->oh_len);
1000 /* We've lost context; don't complain if next one looks bad too */
1001 lost_context = 1;
1002 continue;
1003 }
1004
1005 if (be32_to_cpu(op_head->oh_len) != 0) {
1006 if (*(uint *)ptr == XFS_TRANS_HEADER_MAGIC) {
1007 skip = xlog_print_trans_header(&ptr,
1008 be32_to_cpu(op_head->oh_len));
1009 } else {
1010 switch (*(unsigned short *)ptr) {
1011 case XFS_LI_BUF: {
1012 skip = xlog_print_trans_buffer(&ptr,
1013 be32_to_cpu(op_head->oh_len),
1014 &i, num_ops);
1015 break;
1016 }
1017 case XFS_LI_ICREATE: {
1018 skip = xlog_print_trans_icreate(&ptr,
1019 be32_to_cpu(op_head->oh_len),
1020 &i, num_ops);
1021 break;
1022 }
1023 case XFS_LI_INODE: {
1024 skip = xlog_print_trans_inode(log, &ptr,
1025 be32_to_cpu(op_head->oh_len),
1026 &i, num_ops, continued);
1027 break;
1028 }
1029 case XFS_LI_DQUOT: {
1030 skip = xlog_print_trans_dquot(&ptr,
1031 be32_to_cpu(op_head->oh_len),
1032 &i, num_ops);
1033 break;
1034 }
1035 case XFS_LI_EFI: {
1036 skip = xlog_print_trans_efi(&ptr,
1037 be32_to_cpu(op_head->oh_len));
1038 break;
1039 }
1040 case XFS_LI_EFD: {
1041 skip = xlog_print_trans_efd(&ptr,
1042 be32_to_cpu(op_head->oh_len));
1043 break;
1044 }
1045 case XFS_LI_QUOTAOFF: {
1046 skip = xlog_print_trans_qoff(&ptr,
1047 be32_to_cpu(op_head->oh_len));
1048 break;
1049 }
1050 case XLOG_UNMOUNT_TYPE: {
1051 printf(_("Unmount filesystem\n"));
1052 skip = 0;
1053 break;
1054 }
1055 default: {
1056 if (bad_hdr_warn && !lost_context) {
1057 fprintf(stderr,
1058 _("%s: unknown log operation type (%x)\n"),
1059 progname, *(unsigned short *)ptr);
1060 if (print_exit) {
1061 free(buf);
1062 return BAD_HEADER;
1063 }
1064 } else {
1065 printf(
1066 _("Left over region from split log item\n"));
1067 }
1068 skip = 0;
1069 ptr += be32_to_cpu(op_head->oh_len);
1070 lost_context = 0;
1071 }
1072 } /* switch */
1073 } /* else */
1074 if (skip != 0)
1075 xlog_print_add_to_trans(be32_to_cpu(op_head->oh_tid), skip);
1076 }
1077 }
1078 printf("\n");
1079 free(buf);
1080 return NO_ERROR;
1081 } /* xlog_print_record */
1082
1083
1084 int
1085 xlog_print_rec_head(xlog_rec_header_t *head, int *len, int bad_hdr_warn)
1086 {
1087 int i;
1088 char uub[64];
1089 int datalen,bbs;
1090
1091 if (print_no_print)
1092 return be32_to_cpu(head->h_num_logops);
1093
1094 if (!head->h_magicno)
1095 return ZEROED_LOG;
1096
1097 if (be32_to_cpu(head->h_magicno) != XLOG_HEADER_MAGIC_NUM) {
1098 if (bad_hdr_warn)
1099 printf(_("Header 0x%x wanted 0x%x\n"),
1100 be32_to_cpu(head->h_magicno),
1101 XLOG_HEADER_MAGIC_NUM);
1102 return BAD_HEADER;
1103 }
1104
1105 /* check for cleared blocks written by xlog_clear_stale_blocks() */
1106 if (!head->h_len && !head->h_crc && !head->h_prev_block &&
1107 !head->h_num_logops && !head->h_size)
1108 return CLEARED_BLKS;
1109
1110 datalen=be32_to_cpu(head->h_len);
1111 bbs=BTOBB(datalen);
1112
1113 printf(_("cycle: %d version: %d "),
1114 be32_to_cpu(head->h_cycle),
1115 be32_to_cpu(head->h_version));
1116 print_lsn(" lsn", &head->h_lsn);
1117 print_lsn(" tail_lsn", &head->h_tail_lsn);
1118 printf("\n");
1119 printf(_("length of Log Record: %d prev offset: %d num ops: %d\n"),
1120 datalen,
1121 be32_to_cpu(head->h_prev_block),
1122 be32_to_cpu(head->h_num_logops));
1123
1124 if (print_overwrite) {
1125 printf(_("cycle num overwrites: "));
1126 for (i=0; i< MIN(bbs, XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++)
1127 printf("%d - 0x%x ",
1128 i,
1129 be32_to_cpu(head->h_cycle_data[i]));
1130 printf("\n");
1131 }
1132
1133 platform_uuid_unparse(&head->h_fs_uuid, uub);
1134 printf(_("uuid: %s format: "), uub);
1135 switch (be32_to_cpu(head->h_fmt)) {
1136 case XLOG_FMT_UNKNOWN:
1137 printf(_("unknown\n"));
1138 break;
1139 case XLOG_FMT_LINUX_LE:
1140 printf(_("little endian linux\n"));
1141 break;
1142 case XLOG_FMT_LINUX_BE:
1143 printf(_("big endian linux\n"));
1144 break;
1145 case XLOG_FMT_IRIX_BE:
1146 printf(_("big endian irix\n"));
1147 break;
1148 default:
1149 printf("? (%d)\n", be32_to_cpu(head->h_fmt));
1150 break;
1151 }
1152 printf(_("h_size: %d\n"), be32_to_cpu(head->h_size));
1153
1154 *len = be32_to_cpu(head->h_len);
1155 return(be32_to_cpu(head->h_num_logops));
1156 } /* xlog_print_rec_head */
1157
1158 void
1159 xlog_print_rec_xhead(xlog_rec_ext_header_t *head, int coverage)
1160 {
1161 int i;
1162
1163 print_xlog_xhdr_line();
1164 printf(_("extended-header: cycle: %d\n"), be32_to_cpu(head->xh_cycle));
1165
1166 if (print_overwrite) {
1167 printf(_("cycle num overwrites: "));
1168 for (i = 0; i < coverage; i++)
1169 printf("%d - 0x%x ",
1170 i,
1171 be32_to_cpu(head->xh_cycle_data[i]));
1172 printf("\n");
1173 }
1174 } /* xlog_print_rec_xhead */
1175
1176 static void
1177 print_xlog_bad_zeroed(xfs_daddr_t blkno)
1178 {
1179 print_stars();
1180 printf(_("* ERROR: found data after zeroed blocks block=%-21lld *\n"),
1181 (long long)blkno);
1182 print_stars();
1183 if (print_exit)
1184 xlog_exit("Bad log - data after zeroed blocks");
1185 } /* print_xlog_bad_zeroed */
1186
1187 static void
1188 print_xlog_bad_header(xfs_daddr_t blkno, xfs_caddr_t buf)
1189 {
1190 print_stars();
1191 printf(_("* ERROR: header cycle=%-11d block=%-21lld *\n"),
1192 xlog_get_cycle(buf), (long long)blkno);
1193 print_stars();
1194 if (print_exit)
1195 xlog_exit("Bad log record header");
1196 } /* print_xlog_bad_header */
1197
1198 void
1199 print_xlog_bad_data(xfs_daddr_t blkno)
1200 {
1201 print_stars();
1202 printf(_("* ERROR: data block=%-21lld *\n"),
1203 (long long)blkno);
1204 print_stars();
1205 if (print_exit)
1206 xlog_exit("Bad data in log");
1207 } /* print_xlog_bad_data */
1208
1209 static void
1210 print_xlog_bad_reqd_hdrs(xfs_daddr_t blkno, int num_reqd, int num_hdrs)
1211 {
1212 print_stars();
1213 printf(_("* ERROR: for header block=%lld\n"
1214 "* not enough hdrs for data length, "
1215 "required num = %d, hdr num = %d\n"),
1216 (long long)blkno, num_reqd, num_hdrs);
1217 print_stars();
1218 if (print_exit)
1219 xlog_exit(_("Not enough headers for data length."));
1220 } /* print_xlog_bad_reqd_hdrs */
1221
1222 static void
1223 xlog_reallocate_xhdrs(int num_hdrs, xlog_rec_ext_header_t **ret_xhdrs)
1224 {
1225 int len = (num_hdrs-1) * sizeof(xlog_rec_ext_header_t);
1226
1227 *ret_xhdrs = (xlog_rec_ext_header_t *)realloc(*ret_xhdrs, len);
1228 if (*ret_xhdrs == NULL) {
1229 fprintf(stderr, _("%s: xlog_print: malloc failed for ext hdrs\n"), progname);
1230 exit(1);
1231 }
1232 }
1233
1234 /* for V2 logs read each extra hdr and print it out */
1235 static int
1236 xlog_print_extended_headers(
1237 int fd,
1238 int len,
1239 xfs_daddr_t *blkno,
1240 xlog_rec_header_t *hdr,
1241 int *ret_num_hdrs,
1242 xlog_rec_ext_header_t **ret_xhdrs)
1243 {
1244 int i, j;
1245 int coverage_bb;
1246 int num_hdrs;
1247 int num_required;
1248 char xhbuf[XLOG_HEADER_SIZE];
1249 xlog_rec_ext_header_t *x;
1250
1251 num_required = howmany(len, XLOG_HEADER_CYCLE_SIZE);
1252 num_hdrs = be32_to_cpu(hdr->h_size) / XLOG_HEADER_CYCLE_SIZE;
1253
1254 if (num_required > num_hdrs) {
1255 print_xlog_bad_reqd_hdrs((*blkno)-1, num_required, num_hdrs);
1256 }
1257
1258 if (num_hdrs == 1) {
1259 free(*ret_xhdrs);
1260 *ret_xhdrs = NULL;
1261 *ret_num_hdrs = 1;
1262 return 0;
1263 }
1264
1265 if (*ret_xhdrs == NULL || num_hdrs > *ret_num_hdrs) {
1266 xlog_reallocate_xhdrs(num_hdrs, ret_xhdrs);
1267 }
1268
1269 *ret_num_hdrs = num_hdrs;
1270
1271 /* don't include 1st header */
1272 for (i = 1, x = *ret_xhdrs; i < num_hdrs; i++, (*blkno)++, x++) {
1273 /* read one extra header blk */
1274 if (read(fd, xhbuf, 512) == 0) {
1275 printf(_("%s: physical end of log\n"), progname);
1276 print_xlog_record_line();
1277 /* reached the end so return 1 */
1278 return 1;
1279 }
1280 if (print_only_data) {
1281 printf(_("BLKNO: %lld\n"), (long long)*blkno);
1282 xlog_recover_print_data(xhbuf, 512);
1283 }
1284 else {
1285 if (i == num_hdrs - 1) {
1286 /* last header */
1287 coverage_bb = BTOBB(len) %
1288 (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
1289 }
1290 else {
1291 /* earliear header */
1292 coverage_bb = XLOG_HEADER_CYCLE_SIZE / BBSIZE;
1293 }
1294 xlog_print_rec_xhead((xlog_rec_ext_header_t*)xhbuf, coverage_bb);
1295 }
1296
1297 /* Copy from buffer into xhdrs array for later.
1298 * Could endian convert here but then code later on
1299 * will look asymmetric with the 1 hdr normal case
1300 * which does endian coversion on access.
1301 */
1302 x->xh_cycle = ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle;
1303 for (j = 0; j < XLOG_HEADER_CYCLE_SIZE / BBSIZE; j++) {
1304 x->xh_cycle_data[j] =
1305 ((xlog_rec_ext_header_t*)xhbuf)->xh_cycle_data[j];
1306 }
1307 }
1308 return 0;
1309 }
1310
1311
1312 /*
1313 * This code is gross and needs to be rewritten.
1314 */
1315 void xfs_log_print(struct xlog *log,
1316 int fd,
1317 int print_block_start)
1318 {
1319 char hbuf[XLOG_HEADER_SIZE];
1320 xlog_rec_header_t *hdr = (xlog_rec_header_t *)&hbuf[0];
1321 xlog_rec_ext_header_t *xhdrs = NULL;
1322 int num_ops, len, num_hdrs = 1;
1323 xfs_daddr_t block_end = 0, block_start, blkno, error;
1324 xfs_daddr_t zeroed_blkno = 0, cleared_blkno = 0;
1325 int read_type = FULL_READ;
1326 xfs_caddr_t partial_buf;
1327 int zeroed = 0;
1328 int cleared = 0;
1329 int first_hdr_found = 0;
1330
1331 logBBsize = log->l_logBBsize;
1332
1333 /*
1334 * Normally, block_start and block_end are the same value since we
1335 * are printing the entire log. However, if the start block is given,
1336 * we still end at the end of the logical log.
1337 */
1338 if ((error = xlog_print_find_oldest(log, &block_end))) {
1339 fprintf(stderr, _("%s: problem finding oldest LR\n"), progname);
1340 return;
1341 }
1342 if (print_block_start == -1)
1343 block_start = block_end;
1344 else
1345 block_start = print_block_start;
1346 xlog_print_lseek(log, fd, block_start, SEEK_SET);
1347 blkno = block_start;
1348
1349 for (;;) {
1350 if (read(fd, hbuf, 512) == 0) {
1351 printf(_("%s: physical end of log\n"), progname);
1352 print_xlog_record_line();
1353 break;
1354 }
1355 if (print_only_data) {
1356 printf(_("BLKNO: %lld\n"), (long long)blkno);
1357 xlog_recover_print_data(hbuf, 512);
1358 blkno++;
1359 goto loop;
1360 }
1361 num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found);
1362 blkno++;
1363
1364 if (zeroed && num_ops != ZEROED_LOG) {
1365 printf(_("%s: after %d zeroed blocks\n"), progname, zeroed);
1366 /* once we find zeroed blocks - that's all we expect */
1367 print_xlog_bad_zeroed(blkno-1);
1368 /* reset count since we're assuming previous zeroed blocks
1369 * were bad
1370 */
1371 zeroed = 0;
1372 }
1373
1374 if (num_ops == ZEROED_LOG ||
1375 num_ops == CLEARED_BLKS ||
1376 num_ops == BAD_HEADER) {
1377 if (num_ops == ZEROED_LOG) {
1378 if (zeroed == 0)
1379 zeroed_blkno = blkno-1;
1380 zeroed++;
1381 }
1382 else if (num_ops == CLEARED_BLKS) {
1383 if (cleared == 0)
1384 cleared_blkno = blkno-1;
1385 cleared++;
1386 } else {
1387 if (!first_hdr_found)
1388 block_start = blkno;
1389 else
1390 print_xlog_bad_header(blkno-1, hbuf);
1391 }
1392
1393 goto loop;
1394 }
1395
1396 if (be32_to_cpu(hdr->h_version) == 2) {
1397 if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0)
1398 break;
1399 }
1400
1401 error = xlog_print_record(log, fd, num_ops, len, &read_type, &partial_buf,
1402 hdr, xhdrs, first_hdr_found);
1403 first_hdr_found++;
1404 switch (error) {
1405 case 0: {
1406 blkno += BTOBB(len);
1407 if (print_block_start != -1 &&
1408 blkno >= block_end) /* If start specified, we */
1409 goto end; /* end early */
1410 break;
1411 }
1412 case -1: {
1413 print_xlog_bad_data(blkno-1);
1414 if (print_block_start != -1 &&
1415 blkno >= block_end) /* If start specified, */
1416 goto end; /* we end early */
1417 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1418 goto loop;
1419 }
1420 case PARTIAL_READ: {
1421 print_xlog_record_line();
1422 printf(_("%s: physical end of log\n"), progname);
1423 print_xlog_record_line();
1424 blkno = 0;
1425 xlog_print_lseek(log, fd, 0, SEEK_SET);
1426 /*
1427 * We may have hit the end of the log when we started at 0.
1428 * In this case, just end.
1429 */
1430 if (block_start == 0)
1431 goto end;
1432 goto partial_log_read;
1433 }
1434 default: xlog_panic(_("illegal value"));
1435 }
1436 print_xlog_record_line();
1437 loop:
1438 if (blkno >= logBBsize) {
1439 if (cleared) {
1440 printf(_("%s: skipped %d cleared blocks in range: %lld - %lld\n"),
1441 progname, cleared,
1442 (long long)(cleared_blkno),
1443 (long long)(cleared + cleared_blkno - 1));
1444 if (cleared == logBBsize)
1445 printf(_("%s: totally cleared log\n"), progname);
1446
1447 cleared=0;
1448 }
1449 if (zeroed) {
1450 printf(_("%s: skipped %d zeroed blocks in range: %lld - %lld\n"),
1451 progname, zeroed,
1452 (long long)(zeroed_blkno),
1453 (long long)(zeroed + zeroed_blkno - 1));
1454 if (zeroed == logBBsize)
1455 printf(_("%s: totally zeroed log\n"), progname);
1456
1457 zeroed=0;
1458 }
1459 printf(_("%s: physical end of log\n"), progname);
1460 print_xlog_record_line();
1461 break;
1462 }
1463 }
1464
1465 /* Do we need to print the first part of physical log? */
1466 if (block_start != 0) {
1467 blkno = 0;
1468 xlog_print_lseek(log, fd, 0, SEEK_SET);
1469 for (;;) {
1470 if (read(fd, hbuf, 512) == 0) {
1471 xlog_panic(_("xlog_find_head: bad read"));
1472 }
1473 if (print_only_data) {
1474 printf(_("BLKNO: %lld\n"), (long long)blkno);
1475 xlog_recover_print_data(hbuf, 512);
1476 blkno++;
1477 goto loop2;
1478 }
1479 num_ops = xlog_print_rec_head(hdr, &len, first_hdr_found);
1480 blkno++;
1481
1482 if (num_ops == ZEROED_LOG ||
1483 num_ops == CLEARED_BLKS ||
1484 num_ops == BAD_HEADER) {
1485 /* we only expect zeroed log entries or cleared log
1486 * entries at the end of the _physical_ log,
1487 * so treat them the same as bad blocks here
1488 */
1489 print_xlog_bad_header(blkno-1, hbuf);
1490
1491 if (blkno >= block_end)
1492 break;
1493 continue;
1494 }
1495
1496 if (be32_to_cpu(hdr->h_version) == 2) {
1497 if (xlog_print_extended_headers(fd, len, &blkno, hdr, &num_hdrs, &xhdrs) != 0)
1498 break;
1499 }
1500
1501 partial_log_read:
1502 error= xlog_print_record(log, fd, num_ops, len, &read_type,
1503 &partial_buf, (xlog_rec_header_t *)hbuf,
1504 xhdrs, first_hdr_found);
1505 if (read_type != FULL_READ)
1506 len -= read_type;
1507 read_type = FULL_READ;
1508 if (!error)
1509 blkno += BTOBB(len);
1510 else {
1511 print_xlog_bad_data(blkno-1);
1512 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1513 goto loop2;
1514 }
1515 print_xlog_record_line();
1516 loop2:
1517 if (blkno >= block_end)
1518 break;
1519 }
1520 }
1521
1522 end:
1523 printf(_("%s: logical end of log\n"), progname);
1524 print_xlog_record_line();
1525 }
1526
1527 /*
1528 * if necessary, convert an xfs_inode_log_format struct from 32bit or 64 bit versions
1529 * (which can have different field alignments) to the native version
1530 */
1531 xfs_inode_log_format_t *
1532 xfs_inode_item_format_convert(char *src_buf, uint len, xfs_inode_log_format_t *in_f)
1533 {
1534 /* if we have native format then just return buf without copying data */
1535 if (len == sizeof(xfs_inode_log_format_t)) {
1536 return (xfs_inode_log_format_t *)src_buf;
1537 }
1538
1539 if (len == sizeof(xfs_inode_log_format_32_t)) {
1540 xfs_inode_log_format_32_t *in_f32;
1541
1542 in_f32 = (xfs_inode_log_format_32_t *)src_buf;
1543 in_f->ilf_type = in_f32->ilf_type;
1544 in_f->ilf_size = in_f32->ilf_size;
1545 in_f->ilf_fields = in_f32->ilf_fields;
1546 in_f->ilf_asize = in_f32->ilf_asize;
1547 in_f->ilf_dsize = in_f32->ilf_dsize;
1548 in_f->ilf_ino = in_f32->ilf_ino;
1549 /* copy biggest */
1550 memcpy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid, sizeof(uuid_t));
1551 in_f->ilf_blkno = in_f32->ilf_blkno;
1552 in_f->ilf_len = in_f32->ilf_len;
1553 in_f->ilf_boffset = in_f32->ilf_boffset;
1554 } else {
1555 xfs_inode_log_format_64_t *in_f64;
1556
1557 ASSERT(len == sizeof(xfs_inode_log_format_64_t));
1558 in_f64 = (xfs_inode_log_format_64_t *)src_buf;
1559 in_f->ilf_type = in_f64->ilf_type;
1560 in_f->ilf_size = in_f64->ilf_size;
1561 in_f->ilf_fields = in_f64->ilf_fields;
1562 in_f->ilf_asize = in_f64->ilf_asize;
1563 in_f->ilf_dsize = in_f64->ilf_dsize;
1564 in_f->ilf_ino = in_f64->ilf_ino;
1565 /* copy biggest */
1566 memcpy(&in_f->ilf_u.ilfu_uuid, &in_f64->ilf_u.ilfu_uuid, sizeof(uuid_t));
1567 in_f->ilf_blkno = in_f64->ilf_blkno;
1568 in_f->ilf_len = in_f64->ilf_len;
1569 in_f->ilf_boffset = in_f64->ilf_boffset;
1570 }
1571 return in_f;
1572 }
1573
1574 int
1575 xfs_efi_copy_format(char *buf, uint len, xfs_efi_log_format_t *dst_efi_fmt)
1576 {
1577 uint i;
1578 uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents;
1579 uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t);
1580 uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t);
1581 uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t);
1582
1583 if (len == dst_len) {
1584 memcpy((char *)dst_efi_fmt, buf, len);
1585 return 0;
1586 } else if (len == len32) {
1587 xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf;
1588
1589 dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
1590 dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
1591 dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
1592 dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
1593 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
1594 dst_efi_fmt->efi_extents[i].ext_start =
1595 src_efi_fmt_32->efi_extents[i].ext_start;
1596 dst_efi_fmt->efi_extents[i].ext_len =
1597 src_efi_fmt_32->efi_extents[i].ext_len;
1598 }
1599 return 0;
1600 } else if (len == len64) {
1601 xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf;
1602
1603 dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
1604 dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
1605 dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
1606 dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
1607 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
1608 dst_efi_fmt->efi_extents[i].ext_start =
1609 src_efi_fmt_64->efi_extents[i].ext_start;
1610 dst_efi_fmt->efi_extents[i].ext_len =
1611 src_efi_fmt_64->efi_extents[i].ext_len;
1612 }
1613 return 0;
1614 }
1615 fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"),
1616 progname, len, len32, len64, nextents);
1617 return 1;
1618 }