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