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