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