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