]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - logprint/log_misc.c
Cosmetic configure tweaks to keep xfsprogs in sync with other packages.
[thirdparty/xfsprogs-dev.git] / logprint / log_misc.c
CommitLineData
2bd0ea18 1/*
0d3e0b37 2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
2bd0ea18
NS
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33#include "logprint.h"
34
35#define ZEROED_LOG (-4)
36#define FULL_READ (-3)
37#define PARTIAL_READ (-2)
38#define BAD_HEADER (-1)
39#define NO_ERROR (0)
40
41static int logBBsize;
42char *trans_type[] = {
43 "",
44 "SETATTR",
45 "SETATTR_SIZE",
46 "INACTIVE",
47 "CREATE",
48 "CREATE_TRUNC",
49 "TRUNCATE_FILE",
50 "REMOVE",
51 "LINK",
52 "RENAME",
53 "MKDIR",
54 "RMDIR",
55 "SYMLINK",
56 "SET_DMATTRS",
57 "GROWFS",
58 "STRAT_WRITE",
59 "DIOSTRAT",
60 "WRITE_SYNC",
61 "WRITEID",
62 "ADDAFORK",
63 "ATTRINVAL",
64 "ATRUNCATE",
65 "ATTR_SET",
66 "ATTR_RM",
67 "ATTR_FLAG",
68 "CLEAR_AGI_BUCKET",
69 "QM_SBCHANGE",
70 "DUMMY1",
71 "DUMMY2",
72 "QM_QUOTAOFF",
73 "QM_DQALLOC",
74 "QM_SETQLIM",
75 "QM_DQCLUSTER",
76 "QM_QINOCREATE",
77 "QM_QUOTAOFF_END",
78 "SB_UNIT",
79 "FSYNC_TS",
80 "GROWFSRT_ALLOC",
81 "GROWFSRT_ZERO",
82 "GROWFSRT_FREE",
83 "SWAPEXT",
84};
85
86typedef struct xlog_split_item {
87 struct xlog_split_item *si_next;
88 struct xlog_split_item *si_prev;
89 xlog_tid_t si_tid;
90 int si_skip;
91} xlog_split_item_t;
92
93xlog_split_item_t *split_list = 0;
94
95void
96print_xlog_op_line(void)
97{
98 printf("--------------------------------------"
99 "--------------------------------------\n");
100} /* print_xlog_op_line */
101
102void
103print_xlog_record_line(void)
104{
105 printf("======================================"
106 "======================================\n");
107} /* print_xlog_record_line */
108
109void
110print_stars(void)
111{
112 printf("***********************************"
113 "***********************************\n");
114} /* print_xlog_record_line */
115
116/*
117 * Given a pointer to a data segment, print out the data as if it were
118 * a log operation header.
119 */
120void
121xlog_print_op_header(xlog_op_header_t *op_head,
122 int i,
123 xfs_caddr_t *ptr)
124{
125 xlog_op_header_t hbuf;
126
127 /*
128 * bcopy because on 64/n32, partial reads can cause the op_head
129 * pointer to come in pointing to an odd-numbered byte
130 */
131 bcopy(op_head, &hbuf, sizeof(xlog_op_header_t));
132 op_head = &hbuf;
133 *ptr += sizeof(xlog_op_header_t);
134 printf("Oper (%d): tid: %x len: %d clientid: %s ", i,
135 INT_GET(op_head->oh_tid, ARCH_CONVERT),
136 INT_GET(op_head->oh_len, ARCH_CONVERT),
137 (op_head->oh_clientid == XFS_TRANSACTION ? "TRANS" :
138 (op_head->oh_clientid == XFS_LOG ? "LOG" : "ERROR")));
139 printf("flags: ");
140 if (op_head->oh_flags) {
141 if (op_head->oh_flags & XLOG_START_TRANS)
142 printf("START ");
143 if (op_head->oh_flags & XLOG_COMMIT_TRANS)
144 printf("COMMIT ");
145 if (op_head->oh_flags & XLOG_WAS_CONT_TRANS)
146 printf("WAS_CONT ");
147 if (op_head->oh_flags & XLOG_UNMOUNT_TRANS)
148 printf("UNMOUNT ");
149 if (op_head->oh_flags & XLOG_CONTINUE_TRANS)
150 printf("CONTINUE ");
151 if (op_head->oh_flags & XLOG_END_TRANS)
152 printf("END ");
153 } else {
154 printf("none");
155 }
156 printf("\n");
157} /* xlog_print_op_header */
158
159
160void
161xlog_print_add_to_trans(xlog_tid_t tid,
162 int skip)
163{
164 xlog_split_item_t *item;
165
166 item = (xlog_split_item_t *)calloc(sizeof(xlog_split_item_t), 1);
167 item->si_tid = tid;
168 item->si_skip = skip;
169 item->si_next = split_list;
170 item->si_prev = 0;
171 if (split_list)
172 split_list->si_prev = item;
173 split_list = item;
174} /* xlog_print_add_to_trans */
175
176
177int
178xlog_print_find_tid(xlog_tid_t tid, uint was_cont)
179{
180 xlog_split_item_t *listp = split_list;
181
182 if (!split_list) {
183 if (was_cont != 0) /* Not first time we have used this tid */
184 return 1;
185 else
186 return 0;
187 }
188 while (listp) {
189 if (listp->si_tid == tid)
190 break;
191 listp = listp->si_next;
192 }
193 if (!listp) {
194 return 0;
195 }
196 if (--listp->si_skip == 0) {
197 if (listp == split_list) { /* delete at head */
198 split_list = listp->si_next;
199 if (split_list)
200 split_list->si_prev = NULL;
201 } else {
202 if (listp->si_next)
203 listp->si_next->si_prev = listp->si_prev;
204 listp->si_prev->si_next = listp->si_next;
205 }
206 free(listp);
207 }
208 return 1;
209} /* xlog_print_find_tid */
210
211int
212xlog_print_trans_header(xfs_caddr_t *ptr, int len)
213{
214 xfs_trans_header_t *h;
215 xfs_caddr_t cptr = *ptr;
216 __uint32_t magic;
217 char *magic_c = (char *)&magic;
218
219 *ptr += len;
220
221 magic=*(__uint32_t*)cptr; /* XXX INT_GET soon */
222
150a512d 223 if (len >= 4) {
2bd0ea18 224#if __BYTE_ORDER == __LITTLE_ENDIAN
150a512d 225 printf("%c%c%c%c:",
2bd0ea18
NS
226 magic_c[3], magic_c[2], magic_c[1], magic_c[0]);
227#else
150a512d 228 printf("%c%c%c%c:",
2bd0ea18
NS
229 magic_c[0], magic_c[1], magic_c[2], magic_c[3]);
230#endif
150a512d 231 }
2bd0ea18
NS
232 if (len != sizeof(xfs_trans_header_t)) {
233 printf(" Not enough data to decode further\n");
234 return 1;
235 }
236 h = (xfs_trans_header_t *)cptr;
237 printf(" type: %s tid: %x num_items: %d\n",
238 trans_type[h->th_type], h->th_tid, h->th_num_items);
239 return 0;
240} /* xlog_print_trans_header */
241
242
243int
244xlog_print_trans_buffer(xfs_caddr_t *ptr, int len, int *i, int num_ops)
245{
246 xfs_buf_log_format_t *f;
247 xfs_buf_log_format_v1_t *old_f;
248 xfs_agi_t *agi;
249 xfs_agf_t *agf;
250 xfs_disk_dquot_t *dq;
251 xlog_op_header_t *head = 0;
252 int num, skip;
253 int super_block = 0;
254 int bucket, col, buckets;
255 __int64_t blkno;
256 xfs_buf_log_format_t lbuf;
257 int size, blen, map_size, struct_size;
258 long long x, y;
259
260 /*
261 * bcopy to ensure 8-byte alignment for the long longs in
262 * buf_log_format_t structure
263 */
c3cf3190 264 bcopy(*ptr, &lbuf, MIN(sizeof(xfs_buf_log_format_t), len));
2bd0ea18
NS
265 f = &lbuf;
266 *ptr += len;
267
268 if (f->blf_type == XFS_LI_BUF) {
269 blkno = f->blf_blkno;
270 size = f->blf_size;
271 blen = f->blf_len;
272 map_size = f->blf_map_size;
273 struct_size = sizeof(xfs_buf_log_format_t);
274 } else {
275 old_f = (xfs_buf_log_format_v1_t*)f;
276 blkno = old_f->blf_blkno;
277 size = old_f->blf_size;
278 blen = old_f->blf_len;
279 map_size = old_f->blf_map_size;
280 struct_size = sizeof(xfs_buf_log_format_v1_t);
281 }
282 switch (f->blf_type) {
283 case XFS_LI_BUF:
284 printf("BUF: ");
285 break;
286 case XFS_LI_6_1_BUF:
287 printf("6.1 BUF: ");
288 break;
289 case XFS_LI_5_3_BUF:
290 printf("5.3 BUF: ");
291 break;
2bd0ea18
NS
292 default:
293 printf("UNKNOWN BUF: ");
294 break;
295 }
296 if (len >= struct_size) {
297 ASSERT((len - sizeof(struct_size)) % sizeof(int) == 0);
298 printf("#regs: %d start blkno: %lld (0x%llx) len: %d bmap size: %d\n",
5b64e00a 299 size, (long long)blkno, (unsigned long long)blkno, blen, map_size);
2bd0ea18
NS
300 if (blkno == 0)
301 super_block = 1;
302 } else {
303 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
304 printf("#regs: %d Not printing rest of data\n", f->blf_size);
305 return size;
306 }
307 num = size-1;
308
309 /* Check if all regions in this log item were in the given LR ptr */
310 if (*i+num > num_ops-1) {
311 skip = num - (num_ops-1-*i);
312 num = num_ops-1-*i;
313 } else {
314 skip = 0;
315 }
316 while (num-- > 0) {
317 (*i)++;
318 head = (xlog_op_header_t *)*ptr;
319 xlog_print_op_header(head, *i, ptr);
320 if (super_block) {
321 printf("SUPER BLOCK Buffer: ");
322 if (INT_GET(head->oh_len, ARCH_CONVERT) < 4*8) {
323 printf("Out of space\n");
324 } else {
325 printf("\n");
326 /*
327 * bcopy because *ptr may not be 8-byte aligned
328 */
329 bcopy(*ptr, &x, sizeof(long long));
330 bcopy(*ptr+8, &y, sizeof(long long));
331 printf("icount: %lld ifree: %lld ",
332 INT_GET(x, ARCH_CONVERT),
333 INT_GET(y, ARCH_CONVERT));
334 bcopy(*ptr+16, &x, sizeof(long long));
335 bcopy(*ptr+24, &y, sizeof(long long));
336 printf("fdblks: %lld frext: %lld\n",
337 INT_GET(x, ARCH_CONVERT),
338 INT_GET(y, ARCH_CONVERT));
339 }
340 super_block = 0;
341 } else if (INT_GET(*(uint *)(*ptr), ARCH_CONVERT) == XFS_AGI_MAGIC) {
342 agi = (xfs_agi_t *)(*ptr);
343 printf("AGI Buffer: XAGI ");
344 if (INT_GET(head->oh_len, ARCH_CONVERT) <
345 sizeof(xfs_agi_t) -
346 XFS_AGI_UNLINKED_BUCKETS*sizeof(xfs_agino_t)) {
347 printf("out of space\n");
348 } else {
349 printf("\n");
350 printf("ver: %d ",
351 INT_GET(agi->agi_versionnum, ARCH_CONVERT));
352 printf("seq#: %d len: %d cnt: %d root: %d\n",
353 INT_GET(agi->agi_seqno, ARCH_CONVERT),
354 INT_GET(agi->agi_length, ARCH_CONVERT),
355 INT_GET(agi->agi_count, ARCH_CONVERT),
356 INT_GET(agi->agi_root, ARCH_CONVERT));
357 printf("level: %d free#: 0x%x newino: 0x%x\n",
358 INT_GET(agi->agi_level, ARCH_CONVERT),
359 INT_GET(agi->agi_freecount, ARCH_CONVERT),
360 INT_GET(agi->agi_newino, ARCH_CONVERT));
361 if (INT_GET(head->oh_len, ARCH_CONVERT) == 128) {
362 buckets = 17;
363 } else if (INT_GET(head->oh_len, ARCH_CONVERT) == 256) {
364 buckets = 32 + 17;
365 } else {
c3cf3190
NS
366 if (head->oh_flags & XLOG_CONTINUE_TRANS) {
367 printf("AGI unlinked data skipped ");
368 printf("(CONTINUE set, no space)\n");
369 continue;
370 }
2bd0ea18
NS
371 buckets = XFS_AGI_UNLINKED_BUCKETS;
372 }
373 for (bucket = 0; bucket < buckets;) {
374 printf("bucket[%d - %d]: ", bucket, bucket+3);
375 for (col = 0; col < 4; col++, bucket++) {
376 if (bucket < buckets) {
377 printf("0x%x ",
378 INT_GET(agi->agi_unlinked[bucket], ARCH_CONVERT));
379 }
380 }
381 printf("\n");
382 }
383 }
384 } else if (INT_GET(*(uint *)(*ptr), ARCH_CONVERT) == XFS_AGF_MAGIC) {
385 agf = (xfs_agf_t *)(*ptr);
386 printf("AGF Buffer: XAGF ");
387 if (INT_GET(head->oh_len, ARCH_CONVERT) < sizeof(xfs_agf_t)) {
388 printf("Out of space\n");
389 } else {
390 printf("\n");
391 printf("ver: %d seq#: %d len: %d \n",
392 INT_GET(agf->agf_versionnum, ARCH_CONVERT),
393 INT_GET(agf->agf_seqno, ARCH_CONVERT),
394 INT_GET(agf->agf_length, ARCH_CONVERT));
395 printf("root BNO: %d CNT: %d\n",
396 INT_GET(agf->agf_roots[XFS_BTNUM_BNOi],
397 ARCH_CONVERT),
398 INT_GET(agf->agf_roots[XFS_BTNUM_CNTi],
399 ARCH_CONVERT));
400 printf("level BNO: %d CNT: %d\n",
401 INT_GET(agf->agf_levels[XFS_BTNUM_BNOi],
402 ARCH_CONVERT),
403 INT_GET(agf->agf_levels[XFS_BTNUM_CNTi],
404 ARCH_CONVERT));
405 printf("1st: %d last: %d cnt: %d "
406 "freeblks: %d longest: %d\n",
407 INT_GET(agf->agf_flfirst, ARCH_CONVERT),
408 INT_GET(agf->agf_fllast, ARCH_CONVERT),
409 INT_GET(agf->agf_flcount, ARCH_CONVERT),
410 INT_GET(agf->agf_freeblks, ARCH_CONVERT),
411 INT_GET(agf->agf_longest, ARCH_CONVERT));
412 }
413 } else if (INT_GET(*(uint *)(*ptr), ARCH_CONVERT) == XFS_DQUOT_MAGIC) {
414 dq = (xfs_disk_dquot_t *)(*ptr);
415 printf("DQUOT Buffer: DQ ");
416 if (INT_GET(head->oh_len, ARCH_CONVERT) <
417 sizeof(xfs_disk_dquot_t)) {
418 printf("Out of space\n");
419 }
420 else {
421 printf("\n");
422 printf("ver: %d flags: 0x%x id: %d \n",
423 INT_GET(dq->d_version, ARCH_CONVERT),
424 INT_GET(dq->d_flags, ARCH_CONVERT),
425 INT_GET(dq->d_id, ARCH_CONVERT));
426 printf("blk limits hard: %llu soft: %llu\n",
5b64e00a 427 (unsigned long long)
2bd0ea18 428 INT_GET(dq->d_blk_hardlimit, ARCH_CONVERT),
5b64e00a 429 (unsigned long long)
2bd0ea18
NS
430 INT_GET(dq->d_blk_softlimit, ARCH_CONVERT));
431 printf("blk count: %llu warns: %d timer: %d\n",
5b64e00a 432 (unsigned long long)
2bd0ea18
NS
433 INT_GET(dq->d_bcount, ARCH_CONVERT),
434 INT_GET(dq->d_bwarns, ARCH_CONVERT),
435 INT_GET(dq->d_btimer, ARCH_CONVERT));
436 printf("ino limits hard: %llu soft: %llu\n",
5b64e00a 437 (unsigned long long)
2bd0ea18 438 INT_GET(dq->d_ino_hardlimit, ARCH_CONVERT),
5b64e00a 439 (unsigned long long)
2bd0ea18
NS
440 INT_GET(dq->d_ino_softlimit, ARCH_CONVERT));
441 printf("ino count: %llu warns: %d timer: %d\n",
5b64e00a 442 (unsigned long long)
2bd0ea18
NS
443 INT_GET(dq->d_icount, ARCH_CONVERT),
444 INT_GET(dq->d_iwarns, ARCH_CONVERT),
445 INT_GET(dq->d_itimer, ARCH_CONVERT));
446 }
447 } else {
448 printf("BUF DATA\n");
449 if (print_data) {
450 uint *dp = (uint *)*ptr;
451 int nums = INT_GET(head->oh_len, ARCH_CONVERT) >> 2;
452 int i = 0;
453
454 while (i < nums) {
455 if ((i % 8) == 0)
456 printf("%2x ", i);
457 printf("%8x ", *dp);
458 dp++;
459 i++;
460 if ((i % 8) == 0)
461 printf("\n");
462 }
463 printf("\n");
464 }
465 }
466 *ptr += INT_GET(head->oh_len, ARCH_CONVERT);
467 }
468 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
469 skip++;
470 return skip;
471} /* xlog_print_trans_buffer */
472
473
474int
475xlog_print_trans_efd(xfs_caddr_t *ptr, uint len)
476{
477 xfs_efd_log_format_t *f;
478 xfs_extent_t *ex;
479 int i;
480 xfs_efd_log_format_t lbuf;
481
482 /*
483 * bcopy to ensure 8-byte alignment for the long longs in
484 * xfs_efd_log_format_t structure
485 */
486 bcopy(*ptr, &lbuf, sizeof(xfs_efd_log_format_t));
487 f = &lbuf;
488 *ptr += len;
489 if (len >= sizeof(xfs_efd_log_format_t)) {
490 printf("EFD: #regs: %d num_extents: %d id: 0x%llx\n",
5b64e00a 491 f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id);
2bd0ea18
NS
492 ex = f->efd_extents;
493 for (i=0; i< f->efd_size; i++) {
5b64e00a
NS
494 printf("(s: 0x%llx, l: %d) ",
495 (unsigned long long)ex->ext_start, ex->ext_len);
2bd0ea18
NS
496 if (i % 4 == 3) printf("\n");
497 ex++;
498 }
499 if (i % 4 != 0) printf("\n");
500 return 0;
501 } else {
502 printf("EFD: Not enough data to decode further\n");
503 return 1;
504 }
505} /* xlog_print_trans_efd */
506
507
508int
509xlog_print_trans_efi(xfs_caddr_t *ptr, uint len)
510{
511 xfs_efi_log_format_t *f;
512 xfs_extent_t *ex;
513 int i;
514 xfs_efi_log_format_t lbuf;
515
516 /*
517 * bcopy to ensure 8-byte alignment for the long longs in
518 * xfs_efi_log_format_t structure
519 */
520 bcopy(*ptr, &lbuf, sizeof(xfs_efi_log_format_t));
521 f = &lbuf;
522 *ptr += len;
523 if (len >= sizeof(xfs_efi_log_format_t)) {
524 printf("EFI: #regs: %d num_extents: %d id: 0x%llx\n",
5b64e00a 525 f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id);
2bd0ea18
NS
526 ex = f->efi_extents;
527 for (i=0; i< f->efi_size; i++) {
5b64e00a
NS
528 printf("(s: 0x%llx, l: %d) ",
529 (unsigned long long)ex->ext_start, ex->ext_len);
2bd0ea18
NS
530 if (i % 4 == 3) printf("\n");
531 ex++;
532 }
533 if (i % 4 != 0) printf("\n");
534 return 0;
535 } else {
536 printf("EFI: Not enough data to decode further\n");
537 return 1;
538 }
539} /* xlog_print_trans_efi */
540
541
c3cf3190
NS
542int
543xlog_print_trans_qoff(xfs_caddr_t *ptr, uint len)
544{
545 xfs_qoff_logformat_t *f;
546 xfs_qoff_logformat_t lbuf;
547
548 bcopy(*ptr, &lbuf, sizeof(xfs_qoff_logformat_t));
549 f = &lbuf;
550 *ptr += len;
551 if (len >= sizeof(xfs_qoff_logformat_t)) {
552 printf("QOFF: #regs: %d flags: 0x%x\n", f->qf_size, f->qf_flags);
553 return 0;
554 } else {
555 printf("QOFF: Not enough data to decode further\n");
556 return 1;
557 }
558} /* xlog_print_trans_qoff */
559
560
2bd0ea18
NS
561void
562xlog_print_trans_inode_core(xfs_dinode_core_t *ip)
563{
564 printf("INODE CORE\n");
565 printf("magic 0x%hx mode 0%ho version %d format %d\n",
566 ip->di_magic, ip->di_mode, (int)ip->di_version,
567 (int)ip->di_format);
568 printf("nlink %hd uid %d gid %d\n",
569 ip->di_nlink, ip->di_uid, ip->di_gid);
570 printf("atime 0x%x mtime 0x%x ctime 0x%x\n",
571 ip->di_atime.t_sec, ip->di_mtime.t_sec, ip->di_ctime.t_sec);
572 printf("size 0x%llx nblocks 0x%llx extsize 0x%x nextents 0x%x\n",
5b64e00a
NS
573 (unsigned long long)ip->di_size, (unsigned long long)ip->di_nblocks,
574 ip->di_extsize, ip->di_nextents);
2bd0ea18
NS
575 printf("naextents 0x%x forkoff %d dmevmask 0x%x dmstate 0x%hx\n",
576 ip->di_anextents, (int)ip->di_forkoff, ip->di_dmevmask,
577 ip->di_dmstate);
578 printf("flags 0x%x gen 0x%x\n",
579 ip->di_flags, ip->di_gen);
580}
581
582void
583xlog_print_dir_sf(xfs_dir_shortform_t *sfp, int size)
584{
585 xfs_ino_t ino;
586 int count;
587 int i;
588 char namebuf[257];
589 xfs_dir_sf_entry_t *sfep;
590
591 /* XXX need to determine whether this is v1 or v2, then
592 print appropriate structure */
593
594 printf("SHORTFORM DIRECTORY size %d\n",
595 size);
596 /* bail out for now */
597
598 return;
599
600 printf("SHORTFORM DIRECTORY size %d count %d\n",
601 size, sfp->hdr.count);
602 bcopy(&(sfp->hdr.parent), &ino, sizeof(ino));
5b64e00a 603 printf(".. ino 0x%llx\n", (unsigned long long)INT_GET(ino, ARCH_CONVERT));
2bd0ea18
NS
604
605 count = (uint)(sfp->hdr.count);
606 sfep = &(sfp->list[0]);
607 for (i = 0; i < count; i++) {
608 bcopy(&(sfep->inumber), &ino, sizeof(ino));
609 bcopy((sfep->name), namebuf, sfep->namelen);
610 namebuf[sfep->namelen] = '\0';
611 printf("%s ino 0x%llx namelen %d\n",
5b64e00a 612 namebuf, (unsigned long long)ino, sfep->namelen);
2bd0ea18
NS
613 sfep = XFS_DIR_SF_NEXTENTRY(sfep);
614 }
615}
616
617int
618xlog_print_trans_inode(xfs_caddr_t *ptr, int len, int *i, int num_ops)
619{
620 xfs_inode_log_format_t *f;
621 xfs_inode_log_format_t_v1 *old_f;
622 xfs_dinode_core_t dino;
623 xlog_op_header_t *op_head;
624 int version;
625 xfs_inode_log_format_t lbuf = {0};
626 int mode;
627 int size;
628
629 /*
630 * print inode type header region
631 *
632 * bcopy to ensure 8-byte alignment for the long longs in
633 * xfs_inode_log_format_t structure
634 *
635 * len can be smaller than xfs_inode_log_format_t sometimes... (?)
636 */
637 bcopy(*ptr, &lbuf, MIN(sizeof(xfs_inode_log_format_t), len));
638 version = lbuf.ilf_type;
639 f = &lbuf;
640 (*i)++; /* bump index */
641 *ptr += len;
642 if (version == XFS_LI_5_3_INODE) {
643 old_f = (xfs_inode_log_format_t_v1 *)f;
644 if (len == sizeof(xfs_inode_log_format_t_v1)) {
645 printf("5.3 INODE: #regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
5b64e00a 646 old_f->ilf_size, (unsigned long long)old_f->ilf_ino,
2bd0ea18
NS
647 old_f->ilf_fields, old_f->ilf_dsize);
648 } else {
649 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
650 printf("5.3 INODE: #regs: %d Not printing rest of data\n",
651 old_f->ilf_size);
652 return old_f->ilf_size;
653 }
654 } else {
655 if (len == sizeof(xfs_inode_log_format_t)) {
656 if (version == XFS_LI_6_1_INODE)
657 printf("6.1 INODE: ");
658 else printf("INODE: ");
659 printf("#regs: %d ino: 0x%llx flags: 0x%x dsize: %d\n",
5b64e00a
NS
660 f->ilf_size, (unsigned long long)f->ilf_ino,
661 f->ilf_fields, f->ilf_dsize);
2bd0ea18 662 printf(" blkno: %lld len: %d boff: %d\n",
5b64e00a 663 (long long)f->ilf_blkno, f->ilf_len, f->ilf_boffset);
2bd0ea18
NS
664 } else {
665 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
666 printf("INODE: #regs: %d Not printing rest of data\n",
667 f->ilf_size);
668 return f->ilf_size;
669 }
670 }
671
672 if (*i >= num_ops) /* end of LR */
673 return f->ilf_size-1;
674
675 /* core inode comes 2nd */
676 op_head = (xlog_op_header_t *)*ptr;
677 xlog_print_op_header(op_head, *i, ptr);
678
679 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
680 return f->ilf_size-1;
681 }
682
683 bcopy(*ptr, &dino, sizeof(dino));
684 mode = dino.di_mode & IFMT;
685 size = (int)dino.di_size;
686 xlog_print_trans_inode_core(&dino);
687 *ptr += sizeof(xfs_dinode_core_t);
688
689 if (*i == num_ops-1 && f->ilf_size == 3) {
a981f202 690 return 1;
2bd0ea18
NS
691 }
692
693 /* does anything come next */
694 op_head = (xlog_op_header_t *)*ptr;
695 switch (f->ilf_fields & XFS_ILOG_NONCORE) {
696 case XFS_ILOG_DEXT: {
697 ASSERT(f->ilf_size == 3);
698 (*i)++;
699 xlog_print_op_header(op_head, *i, ptr);
700 printf("EXTENTS inode data\n");
701 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
702 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
703 return 1;
704 }
705 break;
706 }
707 case XFS_ILOG_DBROOT: {
708 ASSERT(f->ilf_size == 3);
709 (*i)++;
710 xlog_print_op_header(op_head, *i, ptr);
711 printf("BTREE inode data\n");
712 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
713 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
714 return 1;
715 }
716 break;
717 }
718 case XFS_ILOG_DDATA: {
719 ASSERT(f->ilf_size == 3);
720 (*i)++;
721 xlog_print_op_header(op_head, *i, ptr);
722 printf("LOCAL inode data\n");
723 if (mode == IFDIR) {
724 xlog_print_dir_sf((xfs_dir_shortform_t*)*ptr, size);
725 }
726 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
a981f202
NS
727 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
728 return 1;
729 }
730 break;
731 }
732 case XFS_ILOG_AEXT: {
733 ASSERT(f->ilf_size == 3);
734 (*i)++;
735 xlog_print_op_header(op_head, *i, ptr);
736 printf("EXTENTS inode attr\n");
737 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
738 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
739 return 1;
740 }
741 break;
742 }
743 case XFS_ILOG_ABROOT: {
744 ASSERT(f->ilf_size == 3);
745 (*i)++;
746 xlog_print_op_header(op_head, *i, ptr);
747 printf("BTREE inode attr\n");
748 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
749 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
750 return 1;
751 }
752 break;
753 }
754 case XFS_ILOG_ADATA: {
755 ASSERT(f->ilf_size == 3);
756 (*i)++;
757 xlog_print_op_header(op_head, *i, ptr);
758 printf("LOCAL inode attr\n");
759 if (mode == IFDIR) {
760 xlog_print_dir_sf((xfs_dir_shortform_t*)*ptr, size);
761 }
762 *ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
763 if (XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) {
2bd0ea18 764 return 1;
a981f202 765 }
2bd0ea18
NS
766 break;
767 }
768 case XFS_ILOG_DEV: {
769 ASSERT(f->ilf_size == 2);
770 printf("DEV inode: no extra region\n");
771 break;
772 }
773 case XFS_ILOG_UUID: {
774 ASSERT(f->ilf_size == 2);
775 printf("UUID inode: no extra region\n");
776 break;
777 }
778 case 0: {
779 ASSERT(f->ilf_size == 2);
780 break;
781 }
782 default: {
783 xlog_panic("xlog_print_trans_inode: illegal inode type");
784 }
785 }
786 return 0;
787} /* xlog_print_trans_inode */
788
789
c3cf3190
NS
790int
791xlog_print_trans_dquot(xfs_caddr_t *ptr, int len, int *i, int num_ops)
792{
793 xfs_dq_logformat_t *f;
794 xfs_dq_logformat_t lbuf = {0};
795 xfs_disk_dquot_t ddq;
878c1b90 796 xlog_op_header_t *head = NULL;
c3cf3190
NS
797 int num, skip;
798
799 /*
800 * print dquot header region
801 *
802 * bcopy to ensure 8-byte alignment for the long longs in
803 * xfs_dq_logformat_t structure
804 */
805 bcopy(*ptr, &lbuf, MIN(sizeof(xfs_dq_logformat_t), len));
806 f = &lbuf;
807 (*i)++; /* bump index */
808 *ptr += len;
809
810 if (len == sizeof(xfs_dq_logformat_t)) {
811 printf("#regs: %d id: 0x%x", f->qlf_size, f->qlf_id);
812 printf(" blkno: %lld len: %d boff: %d\n",
813 (long long)f->qlf_blkno, f->qlf_len, f->qlf_boffset);
814 } else {
815 ASSERT(len >= 4); /* must have at least 4 bytes if != 0 */
816 printf("DQUOT: #regs: %d Not printing rest of data\n",
817 f->qlf_size);
818 return f->qlf_size;
819 }
820 num = f->qlf_size-1;
821
822 /* Check if all regions in this log item were in the given LR ptr */
823 if (*i+num > num_ops-1) {
824 skip = num - (num_ops-1-*i);
825 num = num_ops-1-*i;
826 } else {
827 skip = 0;
828 }
829
830 while (num-- > 0) {
831 head = (xlog_op_header_t *)*ptr;
832 xlog_print_op_header(head, *i, ptr);
833 ASSERT(INT_GET(head->oh_len, ARCH_CONVERT) == sizeof(xfs_disk_dquot_t));
834 bcopy(*ptr, &ddq, sizeof(xfs_disk_dquot_t));
835 printf("DQUOT: magic 0x%hx flags 0%ho\n",
836 INT_GET(ddq.d_magic, ARCH_CONVERT),
837 INT_GET(ddq.d_flags, ARCH_CONVERT));
838 *ptr += INT_GET(head->oh_len, ARCH_CONVERT);
839 }
840 if (head && head->oh_flags & XLOG_CONTINUE_TRANS)
841 skip++;
842 return skip;
843} /* xlog_print_trans_dquot */
844
2bd0ea18
NS
845
846/******************************************************************************
847 *
848 * Log print routines
849 *
850 ******************************************************************************
851 */
852
853void
854xlog_print_lseek(xlog_t *log, int fd, xfs_daddr_t blkno, int whence)
855{
856#define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT)
857 xfs_off_t offset;
858
859 if (whence == SEEK_SET)
860 offset = BBTOOFF64(blkno+log->l_logBBstart);
861 else
862 offset = BBTOOFF64(blkno);
863 if (lseek64(fd, offset, whence) < 0) {
864 fprintf(stderr, "%s: lseek64 to %llu failed: %s\n",
5b64e00a 865 progname, (unsigned long long)offset, strerror(errno));
2bd0ea18
NS
866 exit(1);
867 }
868} /* xlog_print_lseek */
869
870
871void
872print_lsn(xfs_caddr_t string,
873 xfs_lsn_t *lsn,
874 xfs_arch_t arch)
875{
876 printf("%s: %u,%u", string,
877 CYCLE_LSN(*lsn, arch), BLOCK_LSN(*lsn, arch));
878}
879
880
881int
882xlog_print_record(int fd,
883 int num_ops,
884 int len,
885 int *read_type,
886 xfs_caddr_t *partial_buf,
887 xlog_rec_header_t *rhead)
888{
889 xlog_op_header_t *op_head;
890 xlog_rec_header_t *rechead;
891 xfs_caddr_t buf, ptr;
892 int read_len, skip;
893 int ret, n, i;
894
895 if (print_no_print)
896 return NO_ERROR;
897
898 if (!len) {
899 printf("\n");
900 return NO_ERROR;
901 }
902
903 /* read_len must read up to some block boundary */
904 read_len = (int) BBTOB(BTOBB(len));
905
906 /* read_type => don't malloc() new buffer, use old one */
907 if (*read_type == FULL_READ) {
908 if ((ptr = buf = (xfs_caddr_t)malloc(read_len)) == NULL) {
909 fprintf(stderr, "xlog_print_record: malloc failed\n");
910 exit(1);
911 }
912 } else {
913 read_len -= *read_type;
914 buf = (xfs_caddr_t)((__psint_t)(*partial_buf) + (__psint_t)(*read_type));
915 ptr = *partial_buf;
916 }
917 if ((ret = (int) read(fd, buf, read_len)) == -1) {
918 fprintf(stderr, "xlog_print_record: read error\n");
919 exit(1);
920 }
921 /* Did we overflow the end? */
922 if (*read_type == FULL_READ &&
923 BLOCK_LSN(rhead->h_lsn, ARCH_CONVERT)+BTOBB(read_len) >= logBBsize) {
924 *read_type = BBTOB(logBBsize-BLOCK_LSN(rhead->h_lsn, ARCH_CONVERT)-1);
925 *partial_buf = buf;
926 return PARTIAL_READ;
927 }
928
929 /* Did we read everything? */
930 if ((ret == 0 && read_len != 0) || ret != read_len) {
931 *read_type = ret;
932 *partial_buf = buf;
933 return PARTIAL_READ;
934 }
935 if (*read_type != FULL_READ)
936 read_len += *read_type;
937
938 /* Everything read in. Start from beginning of buffer */
939 buf = ptr;
940 for (i = 0; ptr < buf + read_len; ptr += BBSIZE, i++) {
941 rechead = (xlog_rec_header_t *)ptr;
942 if (INT_GET(rechead->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM) {
943 xlog_print_lseek(0, fd, -read_len+i*BBSIZE, SEEK_CUR);
944 free(buf);
945 return -1;
946 } else {
947 if (INT_GET(rhead->h_cycle, ARCH_CONVERT) !=
948 INT_GET(*(uint *)ptr, ARCH_CONVERT)) {
949 if (*read_type == FULL_READ)
950 return -1;
951 else if (INT_GET(rhead->h_cycle, ARCH_CONVERT) + 1 !=
952 INT_GET(*(uint *)ptr, ARCH_CONVERT))
953 return -1;
954 }
955 }
956 INT_SET(*(uint *)ptr, ARCH_CONVERT,
957 INT_GET(rhead->h_cycle_data[i], ARCH_CONVERT));
958 }
959 ptr = buf;
960 for (i=0; i<num_ops; i++) {
961 print_xlog_op_line();
962 op_head = (xlog_op_header_t *)ptr;
963 xlog_print_op_header(op_head, i, &ptr);
964
965 /* print transaction data */
966 if (print_no_data ||
967 ((XLOG_SET(op_head->oh_flags, XLOG_WAS_CONT_TRANS) ||
968 XLOG_SET(op_head->oh_flags, XLOG_CONTINUE_TRANS)) &&
969 INT_GET(op_head->oh_len, ARCH_CONVERT) == 0)) {
970 for (n = 0; n < INT_GET(op_head->oh_len, ARCH_CONVERT); n++) {
971 printf("%c", *ptr);
972 ptr++;
973 }
974 printf("\n");
975 continue;
976 }
977 if (xlog_print_find_tid(INT_GET(op_head->oh_tid, ARCH_CONVERT),
978 op_head->oh_flags & XLOG_WAS_CONT_TRANS)) {
979 printf("Left over region from split log item\n");
980 ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
981 continue;
982 }
983 if (INT_GET(op_head->oh_len, ARCH_CONVERT) != 0) {
984 if (*(uint *)ptr == XFS_TRANS_HEADER_MAGIC) {
985 skip = xlog_print_trans_header(&ptr,
986 INT_GET(op_head->oh_len, ARCH_CONVERT));
987 } else {
988 switch (*(unsigned short *)ptr) {
989 case XFS_LI_5_3_BUF:
990 case XFS_LI_6_1_BUF:
2bd0ea18
NS
991 case XFS_LI_BUF: {
992 skip = xlog_print_trans_buffer(&ptr,
993 INT_GET(op_head->oh_len, ARCH_CONVERT),
994 &i, num_ops);
995 break;
996 }
997 case XFS_LI_5_3_INODE:
998 case XFS_LI_6_1_INODE:
999 case XFS_LI_INODE: {
1000 skip = xlog_print_trans_inode(&ptr,
1001 INT_GET(op_head->oh_len, ARCH_CONVERT),
1002 &i, num_ops);
1003 break;
1004 }
c3cf3190
NS
1005 case XFS_LI_DQUOT: {
1006 skip = xlog_print_trans_dquot(&ptr,
1007 INT_GET(op_head->oh_len, ARCH_CONVERT),
1008 &i, num_ops);
1009 break;
1010 }
2bd0ea18
NS
1011 case XFS_LI_EFI: {
1012 skip = xlog_print_trans_efi(&ptr,
1013 INT_GET(op_head->oh_len, ARCH_CONVERT));
1014 break;
1015 }
1016 case XFS_LI_EFD: {
1017 skip = xlog_print_trans_efd(&ptr,
1018 INT_GET(op_head->oh_len, ARCH_CONVERT));
1019 break;
1020 }
c3cf3190
NS
1021 case XFS_LI_QUOTAOFF: {
1022 skip = xlog_print_trans_qoff(&ptr,
1023 INT_GET(op_head->oh_len, ARCH_CONVERT));
1024 break;
1025 }
2bd0ea18
NS
1026 case XLOG_UNMOUNT_TYPE: {
1027 printf("Unmount filesystem\n");
1028 skip = 0;
1029 break;
1030 }
1031 default: {
1032 fprintf(stderr, "%s: unknown log operation type (%x)\n",
1033 progname, *(unsigned short *)ptr);
1034 skip = 0;
1035 ptr += INT_GET(op_head->oh_len, ARCH_CONVERT);
1036 }
1037 } /* switch */
1038 } /* else */
1039 if (skip != 0)
1040 xlog_print_add_to_trans(INT_GET(op_head->oh_tid, ARCH_CONVERT), skip);
1041 }
1042 }
1043 printf("\n");
1044 free(buf);
1045 return NO_ERROR;
1046} /* xlog_print_record */
1047
1048
1049int
1050xlog_print_rec_head(xlog_rec_header_t *head, int *len)
1051{
1052 int i;
1053 char uub[64];
1054 int datalen,bbs;
1055
1056 if (print_no_print)
1057 return INT_GET(head->h_num_logops, ARCH_CONVERT);
1058
1059 if (INT_ISZERO(head->h_magicno, ARCH_CONVERT))
1060 return ZEROED_LOG;
1061
1062 if (INT_GET(head->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) {
1063 printf("Header 0x%x wanted 0x%x\n",
1064 INT_GET(head->h_magicno, ARCH_CONVERT),
1065 XLOG_HEADER_MAGIC_NUM);
1066 return BAD_HEADER;
1067 }
1068
1069 datalen=INT_GET(head->h_len, ARCH_CONVERT);
1070 bbs=(datalen/BBSIZE)+(datalen%BBSIZE)?1:0;
1071
1072 printf("cycle: %d version: %d ",
1073 INT_GET(head->h_cycle, ARCH_CONVERT),
1074 INT_GET(head->h_version, ARCH_CONVERT));
1075 print_lsn(" lsn", &head->h_lsn, ARCH_CONVERT);
1076 print_lsn(" tail_lsn", &head->h_tail_lsn, ARCH_CONVERT);
1077 printf("\n");
1078 printf("length of Log Record: %d prev offset: %d num ops: %d\n",
1079 datalen,
1080 INT_GET(head->h_prev_block, ARCH_CONVERT),
1081 INT_GET(head->h_num_logops, ARCH_CONVERT));
1082
1083 if (print_overwrite) {
1084 printf("cycle num overwrites: ");
1085 for (i=0; i< bbs; i++)
1086 printf("%d - 0x%x ",
1087 i,
1088 INT_GET(head->h_cycle_data[i], ARCH_CONVERT));
1089 printf("\n");
1090 }
1091
1092 uuid_unparse(head->h_fs_uuid, uub);
1093 printf("uuid: %s format: ", uub);
1094 switch (INT_GET(head->h_fmt, ARCH_CONVERT)) {
1095 case XLOG_FMT_UNKNOWN:
1096 printf("unknown\n");
1097 break;
1098 case XLOG_FMT_LINUX_LE:
1099 printf("little endian linux\n");
1100 break;
1101 case XLOG_FMT_LINUX_BE:
1102 printf("big endian linux\n");
1103 break;
1104 case XLOG_FMT_IRIX_BE:
1105 printf("big endian irix\n");
1106 break;
1107 default:
1108 printf("? (%d)\n", INT_GET(head->h_fmt, ARCH_CONVERT));
1109 break;
1110 }
1111
1112 *len = INT_GET(head->h_len, ARCH_CONVERT);
1113 return(INT_GET(head->h_num_logops, ARCH_CONVERT));
1114} /* xlog_print_rec_head */
1115
1116static void
1117print_xlog_bad_zeroed(xfs_daddr_t blkno)
1118{
1119 print_stars();
1120 printf("* ERROR: found data after zeroed blocks block=%-21lld *\n",
5b64e00a 1121 (long long)blkno);
2bd0ea18
NS
1122 print_stars();
1123 if (print_exit)
1124 xlog_exit("Bad log - data after zeroed blocks");
1125} /* print_xlog_bad_zeroed */
1126
1127static void
1128print_xlog_bad_header(xfs_daddr_t blkno, xfs_caddr_t buf)
1129{
1130 print_stars();
1131 printf("* ERROR: header cycle=%-11d block=%-21lld *\n",
5b64e00a 1132 GET_CYCLE(buf, ARCH_CONVERT), (long long)blkno);
2bd0ea18
NS
1133 print_stars();
1134 if (print_exit)
1135 xlog_exit("Bad log record header");
1136} /* print_xlog_bad_header */
1137
1138void
1139print_xlog_bad_data(xfs_daddr_t blkno)
1140{
1141 print_stars();
1142 printf("* ERROR: data block=%-21lld *\n",
5b64e00a 1143 (long long)blkno);
2bd0ea18
NS
1144 print_stars();
1145 if (print_exit)
1146 xlog_exit("Bad data in log");
1147} /* print_xlog_bad_data */
1148
1149
1150/*
1151 * This code is gross and needs to be rewritten.
1152 */
1153void xfs_log_print(xlog_t *log,
1154 int fd,
1155 int print_block_start)
1156{
1157 char hbuf[XLOG_HEADER_SIZE];
1158 int num_ops, len;
1159 xfs_daddr_t block_end = 0, block_start, blkno, error;
1160 int read_type = FULL_READ;
1161 xfs_caddr_t partial_buf;
1162 int zeroed = 0;
1163
1164 logBBsize = log->l_logBBsize;
1165
1166 /*
1167 * Normally, block_start and block_end are the same value since we
1168 * are printing the entire log. However, if the start block is given,
1169 * we still end at the end of the logical log.
1170 */
27527004 1171 if ((error = xlog_print_find_oldest(log, &block_end))) {
2bd0ea18
NS
1172 fprintf(stderr, "%s: problem finding oldest LR\n", progname);
1173 return;
1174 }
1175 if (print_block_start == -1)
1176 block_start = block_end;
1177 else
1178 block_start = print_block_start;
1179 xlog_print_lseek(log, fd, block_start, SEEK_SET);
1180 blkno = block_start;
1181
1182 for (;;) {
1183 if (read(fd, hbuf, 512) == 0) {
1184 printf("%s: physical end of log\n", progname);
1185 print_xlog_record_line();
1186 break;
1187 }
1188 if (print_only_data) {
5b64e00a 1189 printf("BLKNO: %lld\n", (long long)blkno);
2bd0ea18
NS
1190 xlog_recover_print_data(hbuf, 512);
1191 blkno++;
1192 goto loop;
1193 }
1194 num_ops = xlog_print_rec_head((xlog_rec_header_t *)hbuf, &len);
1195 blkno++;
1196
1197 if (zeroed && num_ops != ZEROED_LOG) {
1198 printf("%s: after %d zeroed blocks\n", progname, zeroed);
1199 /* once we find zeroed blocks - that's all we expect */
1200 print_xlog_bad_zeroed(blkno-1);
1201 /* reset count since we're assuming previous zeroed blocks
1202 * were bad
1203 */
1204 zeroed = 0;
1205 }
1206
1207 if (num_ops == ZEROED_LOG || num_ops == BAD_HEADER) {
1208 if (num_ops == ZEROED_LOG) {
1209 zeroed++;
1210 } else {
1211 print_xlog_bad_header(blkno-1, hbuf);
1212 }
1213
1214 goto loop;
1215 }
1216
1217 error = xlog_print_record(fd, num_ops, len, &read_type, &partial_buf,
1218 (xlog_rec_header_t *)hbuf);
1219 switch (error) {
1220 case 0: {
1221 blkno += BTOBB(len);
1222 if (print_block_start != -1 &&
1223 blkno >= block_end) /* If start specified, we */
1224 goto end; /* end early */
1225 break;
1226 }
1227 case -1: {
1228 print_xlog_bad_data(blkno-1);
1229 if (print_block_start != -1 &&
1230 blkno >= block_end) /* If start specified, */
1231 goto end; /* we end early */
1232 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1233 goto loop;
1234 }
1235 case PARTIAL_READ: {
1236 print_xlog_record_line();
1237 printf("%s: physical end of log\n", progname);
1238 print_xlog_record_line();
1239 blkno = 0;
1240 xlog_print_lseek(log, fd, 0, SEEK_SET);
1241 /*
1242 * We may have hit the end of the log when we started at 0.
1243 * In this case, just end.
1244 */
1245 if (block_start == 0)
1246 goto end;
1247 goto partial_log_read;
1248 }
1249 default: xlog_panic("illegal value");
1250 }
1251 print_xlog_record_line();
1252loop:
1253 if (blkno >= logBBsize) {
1254 if (zeroed) {
1255 printf("%s: skipped %d zeroed blocks\n", progname, zeroed);
1256 if (zeroed == logBBsize)
1257 printf("%s: totally zeroed log\n", progname);
1258
1259 zeroed=0;
1260 }
1261 printf("%s: physical end of log\n", progname);
1262 print_xlog_record_line();
1263 break;
1264 }
1265 }
1266
1267 /* Do we need to print the first part of physical log? */
1268 if (block_start != 0) {
1269 blkno = 0;
1270 xlog_print_lseek(log, fd, 0, SEEK_SET);
1271 for (;;) {
1272 if (read(fd, hbuf, 512) == 0) {
1273 xlog_panic("xlog_find_head: bad read");
1274 }
1275 if (print_only_data) {
5b64e00a 1276 printf("BLKNO: %lld\n", (long long)blkno);
2bd0ea18
NS
1277 xlog_recover_print_data(hbuf, 512);
1278 blkno++;
1279 goto loop2;
1280 }
1281 num_ops = xlog_print_rec_head((xlog_rec_header_t *)hbuf, &len);
1282 blkno++;
1283
1284 if (num_ops == ZEROED_LOG || num_ops == BAD_HEADER) {
1285 /* we only expect zeroed log entries at the end
1286 * of the _physical_ log, so treat them the same
1287 * as bad blocks here
1288 */
1289 print_xlog_bad_header(blkno-1, hbuf);
1290
1291 if (blkno >= block_end)
1292 break;
1293 continue;
1294 }
1295partial_log_read:
1296 error= xlog_print_record(fd, num_ops, len, &read_type,
1297 &partial_buf, (xlog_rec_header_t *)hbuf);
1298 if (read_type != FULL_READ)
1299 len -= read_type;
1300 read_type = FULL_READ;
1301 if (!error)
1302 blkno += BTOBB(len);
1303 else {
1304 print_xlog_bad_data(blkno-1);
1305 xlog_print_lseek(log, fd, blkno, SEEK_SET);
1306 goto loop2;
1307 }
1308 print_xlog_record_line();
1309loop2:
1310 if (blkno >= block_end)
1311 break;
1312 }
1313 }
1314
1315end:
1316 printf("%s: logical end of log\n", progname);
1317 print_xlog_record_line();
1318}