]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - logprint/log_redo.c
xfs_repair: don't crash if da btree is corrupt
[thirdparty/xfsprogs-dev.git] / logprint / log_redo.c
1 /*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * Copyright (c) 2016 Oracle, Inc.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 #include "libxfs.h"
20 #include "libxlog.h"
21
22 #include "logprint.h"
23
24 /* Extent Free Items */
25
26 static int
27 xfs_efi_copy_format(
28 char *buf,
29 uint len,
30 struct xfs_efi_log_format *dst_efi_fmt,
31 int continued)
32 {
33 uint i;
34 uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents;
35 uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t);
36 uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t);
37 uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t);
38
39 if (len == dst_len || continued) {
40 memcpy((char *)dst_efi_fmt, buf, len);
41 return 0;
42 } else if (len == len32) {
43 xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf;
44
45 dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
46 dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
47 dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
48 dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
49 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
50 dst_efi_fmt->efi_extents[i].ext_start =
51 src_efi_fmt_32->efi_extents[i].ext_start;
52 dst_efi_fmt->efi_extents[i].ext_len =
53 src_efi_fmt_32->efi_extents[i].ext_len;
54 }
55 return 0;
56 } else if (len == len64) {
57 xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf;
58
59 dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
60 dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
61 dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
62 dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
63 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
64 dst_efi_fmt->efi_extents[i].ext_start =
65 src_efi_fmt_64->efi_extents[i].ext_start;
66 dst_efi_fmt->efi_extents[i].ext_len =
67 src_efi_fmt_64->efi_extents[i].ext_len;
68 }
69 return 0;
70 }
71 fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"),
72 progname, len, len32, len64, nextents);
73 return 1;
74 }
75
76 int
77 xlog_print_trans_efi(
78 char **ptr,
79 uint src_len,
80 int continued)
81 {
82 xfs_efi_log_format_t *src_f, *f = NULL;
83 uint dst_len;
84 xfs_extent_t *ex;
85 int i;
86 int error = 0;
87 int core_size = offsetof(xfs_efi_log_format_t, efi_extents);
88
89 /*
90 * memmove to ensure 8-byte alignment for the long longs in
91 * xfs_efi_log_format_t structure
92 */
93 if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) {
94 fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname);
95 exit(1);
96 }
97 memmove((char*)src_f, *ptr, src_len);
98 *ptr += src_len;
99
100 /* convert to native format */
101 dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
102
103 if (continued && src_len < core_size) {
104 printf(_("EFI: Not enough data to decode further\n"));
105 error = 1;
106 goto error;
107 }
108
109 if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) {
110 fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname);
111 exit(1);
112 }
113 if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) {
114 error = 1;
115 goto error;
116 }
117
118 printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"),
119 f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id);
120
121 if (continued) {
122 printf(_("EFI free extent data skipped (CONTINUE set, no space)\n"));
123 goto error;
124 }
125
126 ex = f->efi_extents;
127 for (i=0; i < f->efi_nextents; i++) {
128 printf("(s: 0x%llx, l: %d) ",
129 (unsigned long long)ex->ext_start, ex->ext_len);
130 if (i % 4 == 3) printf("\n");
131 ex++;
132 }
133 if (i % 4 != 0)
134 printf("\n");
135 error:
136 free(src_f);
137 free(f);
138 return error;
139 } /* xlog_print_trans_efi */
140
141 void
142 xlog_recover_print_efi(
143 xlog_recover_item_t *item)
144 {
145 xfs_efi_log_format_t *f, *src_f;
146 xfs_extent_t *ex;
147 int i;
148 uint src_len, dst_len;
149
150 src_f = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
151 src_len = item->ri_buf[0].i_len;
152 /*
153 * An xfs_efi_log_format structure contains a variable length array
154 * as the last field.
155 * Each element is of size xfs_extent_32_t or xfs_extent_64_t.
156 * Need to convert to native format.
157 */
158 dst_len = sizeof(xfs_efi_log_format_t) +
159 (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
160 if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) {
161 fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"),
162 progname);
163 exit(1);
164 }
165 if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) {
166 free(f);
167 return;
168 }
169
170 printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"),
171 f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id);
172 ex = f->efi_extents;
173 printf(" ");
174 for (i=0; i< f->efi_nextents; i++) {
175 printf("(s: 0x%llx, l: %d) ",
176 (unsigned long long)ex->ext_start, ex->ext_len);
177 if (i % 4 == 3)
178 printf("\n");
179 ex++;
180 }
181 if (i % 4 != 0)
182 printf("\n");
183 free(f);
184 }
185
186 int
187 xlog_print_trans_efd(char **ptr, uint len)
188 {
189 xfs_efd_log_format_t *f;
190 xfs_efd_log_format_t lbuf;
191 /* size without extents at end */
192 uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t);
193
194 /*
195 * memmove to ensure 8-byte alignment for the long longs in
196 * xfs_efd_log_format_t structure
197 */
198 memmove(&lbuf, *ptr, MIN(core_size, len));
199 f = &lbuf;
200 *ptr += len;
201 if (len >= core_size) {
202 printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"),
203 f->efd_size, f->efd_nextents,
204 (unsigned long long)f->efd_efi_id);
205
206 /* don't print extents as they are not used */
207
208 return 0;
209 } else {
210 printf(_("EFD: Not enough data to decode further\n"));
211 return 1;
212 }
213 } /* xlog_print_trans_efd */
214
215 void
216 xlog_recover_print_efd(
217 xlog_recover_item_t *item)
218 {
219 xfs_efd_log_format_t *f;
220
221 f = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
222 /*
223 * An xfs_efd_log_format structure contains a variable length array
224 * as the last field.
225 * Each element is of size xfs_extent_32_t or xfs_extent_64_t.
226 * However, the extents are never used and won't be printed.
227 */
228 printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"),
229 f->efd_size, f->efd_nextents,
230 (unsigned long long)f->efd_efi_id);
231 }
232
233 /* Reverse Mapping Update Items */
234
235 static int
236 xfs_rui_copy_format(
237 char *buf,
238 uint len,
239 struct xfs_rui_log_format *dst_fmt,
240 int continued)
241 {
242 uint nextents = ((struct xfs_rui_log_format *)buf)->rui_nextents;
243 uint dst_len = xfs_rui_log_format_sizeof(nextents);
244
245 if (len == dst_len || continued) {
246 memcpy((char *)dst_fmt, buf, len);
247 return 0;
248 }
249 fprintf(stderr, _("%s: bad size of RUI format: %u; expected %u; nextents = %u\n"),
250 progname, len, dst_len, nextents);
251 return 1;
252 }
253
254 int
255 xlog_print_trans_rui(
256 char **ptr,
257 uint src_len,
258 int continued)
259 {
260 struct xfs_rui_log_format *src_f, *f = NULL;
261 uint dst_len;
262 uint nextents;
263 struct xfs_map_extent *ex;
264 int i;
265 int error = 0;
266 int core_size;
267
268 core_size = offsetof(struct xfs_rui_log_format, rui_extents);
269
270 /*
271 * memmove to ensure 8-byte alignment for the long longs in
272 * struct xfs_rui_log_format structure
273 */
274 src_f = malloc(src_len);
275 if (src_f == NULL) {
276 fprintf(stderr, _("%s: %s: malloc failed\n"),
277 progname, __func__);
278 exit(1);
279 }
280 memmove((char*)src_f, *ptr, src_len);
281 *ptr += src_len;
282
283 /* convert to native format */
284 nextents = src_f->rui_nextents;
285 dst_len = xfs_rui_log_format_sizeof(nextents);
286
287 if (continued && src_len < core_size) {
288 printf(_("RUI: Not enough data to decode further\n"));
289 error = 1;
290 goto error;
291 }
292
293 f = malloc(dst_len);
294 if (f == NULL) {
295 fprintf(stderr, _("%s: %s: malloc failed\n"),
296 progname, __func__);
297 exit(1);
298 }
299 if (xfs_rui_copy_format((char *)src_f, src_len, f, continued)) {
300 error = 1;
301 goto error;
302 }
303
304 printf(_("RUI: #regs: %d num_extents: %d id: 0x%llx\n"),
305 f->rui_size, f->rui_nextents, (unsigned long long)f->rui_id);
306
307 if (continued) {
308 printf(_("RUI extent data skipped (CONTINUE set, no space)\n"));
309 goto error;
310 }
311
312 ex = f->rui_extents;
313 for (i=0; i < f->rui_nextents; i++) {
314 printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ",
315 (unsigned long long)ex->me_startblock, ex->me_len,
316 (long long)ex->me_owner,
317 (unsigned long long)ex->me_startoff, ex->me_flags);
318 printf("\n");
319 ex++;
320 }
321 error:
322 free(src_f);
323 free(f);
324 return error;
325 }
326
327 void
328 xlog_recover_print_rui(
329 struct xlog_recover_item *item)
330 {
331 char *src_f;
332 uint src_len;
333
334 src_f = item->ri_buf[0].i_addr;
335 src_len = item->ri_buf[0].i_len;
336
337 xlog_print_trans_rui(&src_f, src_len, 0);
338 }
339
340 int
341 xlog_print_trans_rud(
342 char **ptr,
343 uint len)
344 {
345 struct xfs_rud_log_format *f;
346 struct xfs_rud_log_format lbuf;
347
348 /* size without extents at end */
349 uint core_size = sizeof(struct xfs_rud_log_format);
350
351 /*
352 * memmove to ensure 8-byte alignment for the long longs in
353 * xfs_efd_log_format_t structure
354 */
355 memmove(&lbuf, *ptr, MIN(core_size, len));
356 f = &lbuf;
357 *ptr += len;
358 if (len >= core_size) {
359 printf(_("RUD: #regs: %d id: 0x%llx\n"),
360 f->rud_size,
361 (unsigned long long)f->rud_rui_id);
362
363 /* don't print extents as they are not used */
364
365 return 0;
366 } else {
367 printf(_("RUD: Not enough data to decode further\n"));
368 return 1;
369 }
370 }
371
372 void
373 xlog_recover_print_rud(
374 struct xlog_recover_item *item)
375 {
376 char *f;
377
378 f = item->ri_buf[0].i_addr;
379 xlog_print_trans_rud(&f, sizeof(struct xfs_rud_log_format));
380 }
381
382 /* Reference Count Update Items */
383
384 static int
385 xfs_cui_copy_format(
386 struct xfs_cui_log_format *cui,
387 uint len,
388 struct xfs_cui_log_format *dst_fmt,
389 int continued)
390 {
391 uint nextents;
392 uint dst_len;
393
394 nextents = cui->cui_nextents;
395 dst_len = xfs_cui_log_format_sizeof(nextents);
396
397 if (len == dst_len || continued) {
398 memcpy(dst_fmt, cui, len);
399 return 0;
400 }
401 fprintf(stderr, _("%s: bad size of CUI format: %u; expected %u; nextents = %u\n"),
402 progname, len, dst_len, nextents);
403 return 1;
404 }
405
406 int
407 xlog_print_trans_cui(
408 char **ptr,
409 uint src_len,
410 int continued)
411 {
412 struct xfs_cui_log_format *src_f, *f = NULL;
413 uint dst_len;
414 uint nextents;
415 struct xfs_phys_extent *ex;
416 int i;
417 int error = 0;
418 int core_size;
419
420 core_size = offsetof(struct xfs_cui_log_format, cui_extents);
421
422 src_f = malloc(src_len);
423 if (src_f == NULL) {
424 fprintf(stderr, _("%s: %s: malloc failed\n"),
425 progname, __func__);
426 exit(1);
427 }
428 memcpy(src_f, *ptr, src_len);
429 *ptr += src_len;
430
431 /* convert to native format */
432 nextents = src_f->cui_nextents;
433 dst_len = xfs_cui_log_format_sizeof(nextents);
434
435 if (continued && src_len < core_size) {
436 printf(_("CUI: Not enough data to decode further\n"));
437 error = 1;
438 goto error;
439 }
440
441 f = malloc(dst_len);
442 if (f == NULL) {
443 fprintf(stderr, _("%s: %s: malloc failed\n"),
444 progname, __func__);
445 exit(1);
446 }
447 if (xfs_cui_copy_format(src_f, src_len, f, continued)) {
448 error = 1;
449 goto error;
450 }
451
452 printf(_("CUI: #regs: %d num_extents: %d id: 0x%llx\n"),
453 f->cui_size, f->cui_nextents, (unsigned long long)f->cui_id);
454
455 if (continued) {
456 printf(_("CUI extent data skipped (CONTINUE set, no space)\n"));
457 goto error;
458 }
459
460 ex = f->cui_extents;
461 for (i=0; i < f->cui_nextents; i++) {
462 printf("(s: 0x%llx, l: %d, f: 0x%x) ",
463 (unsigned long long)ex->pe_startblock, ex->pe_len,
464 ex->pe_flags);
465 printf("\n");
466 ex++;
467 }
468 error:
469 free(src_f);
470 free(f);
471 return error;
472 }
473
474 void
475 xlog_recover_print_cui(
476 struct xlog_recover_item *item)
477 {
478 char *src_f;
479 uint src_len;
480
481 src_f = item->ri_buf[0].i_addr;
482 src_len = item->ri_buf[0].i_len;
483
484 xlog_print_trans_cui(&src_f, src_len, 0);
485 }
486
487 int
488 xlog_print_trans_cud(
489 char **ptr,
490 uint len)
491 {
492 struct xfs_cud_log_format *f;
493 struct xfs_cud_log_format lbuf;
494
495 /* size without extents at end */
496 uint core_size = sizeof(struct xfs_cud_log_format);
497
498 memcpy(&lbuf, *ptr, MIN(core_size, len));
499 f = &lbuf;
500 *ptr += len;
501 if (len >= core_size) {
502 printf(_("CUD: #regs: %d id: 0x%llx\n"),
503 f->cud_size,
504 (unsigned long long)f->cud_cui_id);
505
506 /* don't print extents as they are not used */
507
508 return 0;
509 } else {
510 printf(_("CUD: Not enough data to decode further\n"));
511 return 1;
512 }
513 }
514
515 void
516 xlog_recover_print_cud(
517 struct xlog_recover_item *item)
518 {
519 char *f;
520
521 f = item->ri_buf[0].i_addr;
522 xlog_print_trans_cud(&f, sizeof(struct xfs_cud_log_format));
523 }
524
525 /* Block Mapping Update Items */
526
527 static int
528 xfs_bui_copy_format(
529 struct xfs_bui_log_format *bui,
530 uint len,
531 struct xfs_bui_log_format *dst_fmt,
532 int continued)
533 {
534 uint nextents;
535 uint dst_len;
536
537 nextents = bui->bui_nextents;
538 dst_len = xfs_bui_log_format_sizeof(nextents);
539
540 if (len == dst_len || continued) {
541 memcpy(dst_fmt, bui, len);
542 return 0;
543 }
544 fprintf(stderr, _("%s: bad size of BUI format: %u; expected %u; nextents = %u\n"),
545 progname, len, dst_len, nextents);
546 return 1;
547 }
548
549 int
550 xlog_print_trans_bui(
551 char **ptr,
552 uint src_len,
553 int continued)
554 {
555 struct xfs_bui_log_format *src_f, *f = NULL;
556 uint dst_len;
557 uint nextents;
558 struct xfs_map_extent *ex;
559 int i;
560 int error = 0;
561 int core_size;
562
563 core_size = offsetof(struct xfs_bui_log_format, bui_extents);
564
565 src_f = malloc(src_len);
566 if (src_f == NULL) {
567 fprintf(stderr, _("%s: %s: malloc failed\n"),
568 progname, __func__);
569 exit(1);
570 }
571 memcpy(src_f, *ptr, src_len);
572 *ptr += src_len;
573
574 /* convert to native format */
575 nextents = src_f->bui_nextents;
576 dst_len = xfs_bui_log_format_sizeof(nextents);
577
578 if (continued && src_len < core_size) {
579 printf(_("BUI: Not enough data to decode further\n"));
580 error = 1;
581 goto error;
582 }
583
584 f = malloc(dst_len);
585 if (f == NULL) {
586 fprintf(stderr, _("%s: %s: malloc failed\n"),
587 progname, __func__);
588 exit(1);
589 }
590 if (xfs_bui_copy_format(src_f, src_len, f, continued)) {
591 error = 1;
592 goto error;
593 }
594
595 printf(_("BUI: #regs: %d num_extents: %d id: 0x%llx\n"),
596 f->bui_size, f->bui_nextents, (unsigned long long)f->bui_id);
597
598 if (continued) {
599 printf(_("BUI extent data skipped (CONTINUE set, no space)\n"));
600 goto error;
601 }
602
603 ex = f->bui_extents;
604 for (i=0; i < f->bui_nextents; i++) {
605 printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ",
606 (unsigned long long)ex->me_startblock, ex->me_len,
607 (long long)ex->me_owner,
608 (unsigned long long)ex->me_startoff, ex->me_flags);
609 printf("\n");
610 ex++;
611 }
612 error:
613 free(src_f);
614 free(f);
615 return error;
616 }
617
618 void
619 xlog_recover_print_bui(
620 struct xlog_recover_item *item)
621 {
622 char *src_f;
623 uint src_len;
624
625 src_f = item->ri_buf[0].i_addr;
626 src_len = item->ri_buf[0].i_len;
627
628 xlog_print_trans_bui(&src_f, src_len, 0);
629 }
630
631 int
632 xlog_print_trans_bud(
633 char **ptr,
634 uint len)
635 {
636 struct xfs_bud_log_format *f;
637 struct xfs_bud_log_format lbuf;
638
639 /* size without extents at end */
640 uint core_size = sizeof(struct xfs_bud_log_format);
641
642 memcpy(&lbuf, *ptr, MIN(core_size, len));
643 f = &lbuf;
644 *ptr += len;
645 if (len >= core_size) {
646 printf(_("BUD: #regs: %d id: 0x%llx\n"),
647 f->bud_size,
648 (unsigned long long)f->bud_bui_id);
649
650 /* don't print extents as they are not used */
651
652 return 0;
653 } else {
654 printf(_("BUD: Not enough data to decode further\n"));
655 return 1;
656 }
657 }
658
659 void
660 xlog_recover_print_bud(
661 struct xlog_recover_item *item)
662 {
663 char *f;
664
665 f = item->ri_buf[0].i_addr;
666 xlog_print_trans_bud(&f, sizeof(struct xfs_bud_log_format));
667 }