]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - logprint/log_print_all.c
xfs: introduce inode log format object
[thirdparty/xfsprogs-dev.git] / logprint / log_print_all.c
1 /*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 #include "libxfs.h"
19 #include "libxlog.h"
20
21 #include "logprint.h"
22
23 /*
24 * Start is defined to be the block pointing to the oldest valid log record.
25 */
26 int
27 xlog_print_find_oldest(
28 struct xlog *log,
29 xfs_daddr_t *last_blk)
30 {
31 xfs_buf_t *bp;
32 xfs_daddr_t first_blk;
33 uint first_half_cycle, last_half_cycle;
34 int error = 0;
35
36 if (xlog_find_zeroed(log, &first_blk))
37 return 0;
38
39 first_blk = 0; /* read first block */
40 bp = xlog_get_bp(log, 1);
41 xlog_bread_noalign(log, 0, 1, bp);
42 first_half_cycle = xlog_get_cycle(XFS_BUF_PTR(bp));
43 *last_blk = log->l_logBBsize-1; /* read last block */
44 xlog_bread_noalign(log, *last_blk, 1, bp);
45 last_half_cycle = xlog_get_cycle(XFS_BUF_PTR(bp));
46 ASSERT(last_half_cycle != 0);
47
48 if (first_half_cycle == last_half_cycle) /* all cycle nos are same */
49 *last_blk = 0;
50 else /* have 1st and last; look for middle cycle */
51 error = xlog_find_cycle_start(log, bp, first_blk,
52 last_blk, last_half_cycle);
53
54 xlog_put_bp(bp);
55 return error;
56 }
57
58 void
59 xlog_recover_print_data(
60 char *p,
61 int len)
62 {
63 if (print_data) {
64 uint *dp = (uint *)p;
65 int nums = len >> 2;
66 int j = 0;
67
68 while (j < nums) {
69 if ((j % 8) == 0)
70 printf("%2x ", j);
71 printf("%8x ", *dp);
72 dp++;
73 j++;
74 if ((j % 8) == 0)
75 printf("\n");
76 }
77 printf("\n");
78 }
79 }
80
81 STATIC void
82 xlog_recover_print_buffer(
83 xlog_recover_item_t *item)
84 {
85 xfs_agi_t *agi;
86 xfs_agf_t *agf;
87 xfs_buf_log_format_t *f;
88 char *p;
89 int len, num, i;
90 xfs_daddr_t blkno;
91 xfs_disk_dquot_t *ddq;
92
93 f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr;
94 printf(" ");
95 ASSERT(f->blf_type == XFS_LI_BUF);
96 printf(_("BUF: #regs:%d start blkno:0x%llx len:%d bmap size:%d flags:0x%x\n"),
97 f->blf_size, (long long)f->blf_blkno, f->blf_len, f->blf_map_size, f->blf_flags);
98 blkno = (xfs_daddr_t)f->blf_blkno;
99 num = f->blf_size-1;
100 i = 1;
101 while (num-- > 0) {
102 p = item->ri_buf[i].i_addr;
103 len = item->ri_buf[i].i_len;
104 i++;
105 if (blkno == 0) { /* super block */
106 printf(_(" SUPER Block Buffer:\n"));
107 if (!print_buffer)
108 continue;
109 printf(_(" icount:%llu ifree:%llu "),
110 (unsigned long long)
111 be64_to_cpu(*(__be64 *)(p)),
112 (unsigned long long)
113 be64_to_cpu(*(__be64 *)(p+8)));
114 printf(_("fdblks:%llu frext:%llu\n"),
115 (unsigned long long)
116 be64_to_cpu(*(__be64 *)(p+16)),
117 (unsigned long long)
118 be64_to_cpu(*(__be64 *)(p+24)));
119 printf(_(" sunit:%u swidth:%u\n"),
120 be32_to_cpu(*(__be32 *)(p+56)),
121 be32_to_cpu(*(__be32 *)(p+60)));
122 } else if (be32_to_cpu(*(__be32 *)p) == XFS_AGI_MAGIC) {
123 int bucket, buckets;
124 agi = (xfs_agi_t *)p;
125 printf(_(" AGI Buffer: (XAGI)\n"));
126 if (!print_buffer)
127 continue;
128 printf(_(" ver:%d "),
129 be32_to_cpu(agi->agi_versionnum));
130 printf(_("seq#:%d len:%d cnt:%d root:%d\n"),
131 be32_to_cpu(agi->agi_seqno),
132 be32_to_cpu(agi->agi_length),
133 be32_to_cpu(agi->agi_count),
134 be32_to_cpu(agi->agi_root));
135 printf(_(" level:%d free#:0x%x newino:0x%x\n"),
136 be32_to_cpu(agi->agi_level),
137 be32_to_cpu(agi->agi_freecount),
138 be32_to_cpu(agi->agi_newino));
139 if (len == 128) {
140 buckets = 17;
141 } else if (len == 256) {
142 buckets = 32 + 17;
143 } else {
144 buckets = XFS_AGI_UNLINKED_BUCKETS;
145 }
146 for (bucket = 0; bucket < buckets;) {
147 int col;
148 printf(_("bucket[%d - %d]: "), bucket, bucket+3);
149 for (col = 0; col < 4; col++, bucket++) {
150 if (bucket < buckets) {
151 printf("0x%x ",
152 be32_to_cpu(agi->agi_unlinked[bucket]));
153 }
154 }
155 printf("\n");
156 }
157 } else if (be32_to_cpu(*(__be32 *)p) == XFS_AGF_MAGIC) {
158 agf = (xfs_agf_t *)p;
159 printf(_(" AGF Buffer: (XAGF)\n"));
160 if (!print_buffer)
161 continue;
162 printf(_(" ver:%d seq#:%d len:%d \n"),
163 be32_to_cpu(agf->agf_versionnum),
164 be32_to_cpu(agf->agf_seqno),
165 be32_to_cpu(agf->agf_length));
166 printf(_(" root BNO:%d CNT:%d\n"),
167 be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]),
168 be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi]));
169 printf(_(" level BNO:%d CNT:%d\n"),
170 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]),
171 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
172 printf(_(" 1st:%d last:%d cnt:%d "
173 "freeblks:%d longest:%d\n"),
174 be32_to_cpu(agf->agf_flfirst),
175 be32_to_cpu(agf->agf_fllast),
176 be32_to_cpu(agf->agf_flcount),
177 be32_to_cpu(agf->agf_freeblks),
178 be32_to_cpu(agf->agf_longest));
179 } else if (*(uint *)p == XFS_DQUOT_MAGIC) {
180 ddq = (xfs_disk_dquot_t *)p;
181 printf(_(" DQUOT Buffer:\n"));
182 if (!print_buffer)
183 continue;
184 printf(_(" UIDs 0x%lx-0x%lx\n"),
185 (unsigned long)be32_to_cpu(ddq->d_id),
186 (unsigned long)be32_to_cpu(ddq->d_id) +
187 (BBTOB(f->blf_len) / sizeof(xfs_dqblk_t)) - 1);
188 } else {
189 printf(_(" BUF DATA\n"));
190 if (!print_buffer) continue;
191 xlog_recover_print_data(p, len);
192 }
193 }
194 }
195
196 STATIC void
197 xlog_recover_print_quotaoff(
198 xlog_recover_item_t *item)
199 {
200 xfs_qoff_logformat_t *qoff_f;
201 char str[32] = { 0 };
202
203 qoff_f = (xfs_qoff_logformat_t *)item->ri_buf[0].i_addr;
204 ASSERT(qoff_f);
205 if (qoff_f->qf_flags & XFS_UQUOTA_ACCT)
206 strcat(str, "USER QUOTA");
207 if (qoff_f->qf_flags & XFS_GQUOTA_ACCT)
208 strcat(str, "GROUP QUOTA");
209 if (qoff_f->qf_flags & XFS_PQUOTA_ACCT)
210 strcat(str, "PROJECT QUOTA");
211 printf(_("\tQUOTAOFF: #regs:%d type:%s\n"),
212 qoff_f->qf_size, str);
213 }
214
215 STATIC void
216 xlog_recover_print_dquot(
217 xlog_recover_item_t *item)
218 {
219 xfs_dq_logformat_t *f;
220 xfs_disk_dquot_t *d;
221
222 f = (xfs_dq_logformat_t *)item->ri_buf[0].i_addr;
223 ASSERT(f);
224 ASSERT(f->qlf_len == 1);
225 d = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr;
226 printf(_("\tDQUOT: #regs:%d blkno:%lld boffset:%u id: %d\n"),
227 f->qlf_size, (long long)f->qlf_blkno, f->qlf_boffset, f->qlf_id);
228 if (!print_quota)
229 return;
230 printf(_("\t\tmagic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n"),
231 be16_to_cpu(d->d_magic),
232 d->d_version,
233 be32_to_cpu(d->d_id),
234 be32_to_cpu(d->d_id));
235 printf(_("\t\tblk_hard 0x%x\tblk_soft 0x%x\tino_hard 0x%x"
236 "\tino_soft 0x%x\n"),
237 (int)be64_to_cpu(d->d_blk_hardlimit),
238 (int)be64_to_cpu(d->d_blk_softlimit),
239 (int)be64_to_cpu(d->d_ino_hardlimit),
240 (int)be64_to_cpu(d->d_ino_softlimit));
241 printf(_("\t\tbcount 0x%x (%d) icount 0x%x (%d)\n"),
242 (int)be64_to_cpu(d->d_bcount),
243 (int)be64_to_cpu(d->d_bcount),
244 (int)be64_to_cpu(d->d_icount),
245 (int)be64_to_cpu(d->d_icount));
246 printf(_("\t\tbtimer 0x%x itimer 0x%x \n"),
247 (int)be32_to_cpu(d->d_btimer),
248 (int)be32_to_cpu(d->d_itimer));
249 }
250
251 STATIC void
252 xlog_recover_print_inode_core(
253 struct xfs_log_dinode *di)
254 {
255 printf(_(" CORE inode:\n"));
256 if (!print_inode)
257 return;
258 printf(_(" magic:%c%c mode:0x%x ver:%d format:%d "
259 "onlink:%d\n"),
260 (di->di_magic>>8) & 0xff, di->di_magic & 0xff,
261 di->di_mode, di->di_version, di->di_format, di->di_onlink);
262 printf(_(" uid:%d gid:%d nlink:%d projid:0x%04x%04x\n"),
263 di->di_uid, di->di_gid, di->di_nlink,
264 di->di_projid_hi, di->di_projid_lo);
265 printf(_(" atime:%d mtime:%d ctime:%d\n"),
266 di->di_atime.t_sec, di->di_mtime.t_sec, di->di_ctime.t_sec);
267 printf(_(" flushiter:%d\n"), di->di_flushiter);
268 printf(_(" size:0x%llx nblks:0x%llx exsize:%d "
269 "nextents:%d anextents:%d\n"), (unsigned long long)
270 di->di_size, (unsigned long long)di->di_nblocks,
271 di->di_extsize, di->di_nextents, (int)di->di_anextents);
272 printf(_(" forkoff:%d dmevmask:0x%x dmstate:%d flags:0x%x "
273 "gen:%d\n"),
274 (int)di->di_forkoff, di->di_dmevmask, (int)di->di_dmstate,
275 (int)di->di_flags, di->di_gen);
276 }
277
278 STATIC void
279 xlog_recover_print_inode(
280 xlog_recover_item_t *item)
281 {
282 xfs_inode_log_format_t f_buf;
283 xfs_inode_log_format_t *f;
284 int attr_index;
285 int hasdata;
286 int hasattr;
287
288 ASSERT(item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_32_t) ||
289 item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_64_t));
290 f = xfs_inode_item_format_convert(item->ri_buf[0].i_addr, item->ri_buf[0].i_len, &f_buf);
291
292 printf(_(" INODE: #regs:%d ino:0x%llx flags:0x%x dsize:%d\n"),
293 f->ilf_size, (unsigned long long)f->ilf_ino, f->ilf_fields,
294 f->ilf_dsize);
295
296 /* core inode comes 2nd */
297 ASSERT(item->ri_buf[1].i_len == xfs_log_dinode_size(2) ||
298 item->ri_buf[1].i_len == xfs_log_dinode_size(3));
299 xlog_recover_print_inode_core((struct xfs_log_dinode *)
300 item->ri_buf[1].i_addr);
301
302 hasdata = (f->ilf_fields & XFS_ILOG_DFORK) != 0;
303 hasattr = (f->ilf_fields & XFS_ILOG_AFORK) != 0;
304 /* does anything come next */
305 switch (f->ilf_fields & (XFS_ILOG_DFORK|XFS_ILOG_DEV|XFS_ILOG_UUID)) {
306 case XFS_ILOG_DEXT:
307 ASSERT(f->ilf_size == 3 + hasattr);
308 printf(_(" DATA FORK EXTENTS inode data:\n"));
309 if (print_inode && print_data)
310 xlog_recover_print_data(item->ri_buf[2].i_addr,
311 item->ri_buf[2].i_len);
312 break;
313 case XFS_ILOG_DBROOT:
314 ASSERT(f->ilf_size == 3 + hasattr);
315 printf(_(" DATA FORK BTREE inode data:\n"));
316 if (print_inode && print_data)
317 xlog_recover_print_data(item->ri_buf[2].i_addr,
318 item->ri_buf[2].i_len);
319 break;
320 case XFS_ILOG_DDATA:
321 ASSERT(f->ilf_size == 3 + hasattr);
322 printf(_(" DATA FORK LOCAL inode data:\n"));
323 if (print_inode && print_data)
324 xlog_recover_print_data(item->ri_buf[2].i_addr,
325 item->ri_buf[2].i_len);
326 break;
327 case XFS_ILOG_DEV:
328 ASSERT(f->ilf_size == 2 + hasattr);
329 printf(_(" DEV inode: no extra region\n"));
330 break;
331 case XFS_ILOG_UUID:
332 ASSERT(f->ilf_size == 2 + hasattr);
333 printf(_(" UUID inode: no extra region\n"));
334 break;
335
336 case 0:
337 ASSERT(f->ilf_size == 2 + hasattr);
338 break;
339 default:
340 xlog_panic("xlog_print_trans_inode: illegal inode type");
341 }
342
343 if (hasattr) {
344 attr_index = 2 + hasdata;
345 switch (f->ilf_fields & XFS_ILOG_AFORK) {
346 case XFS_ILOG_AEXT:
347 ASSERT(f->ilf_size == 3 + hasdata);
348 printf(_(" ATTR FORK EXTENTS inode data:\n"));
349 if (print_inode && print_data)
350 xlog_recover_print_data(
351 item->ri_buf[attr_index].i_addr,
352 item->ri_buf[attr_index].i_len);
353 break;
354 case XFS_ILOG_ABROOT:
355 ASSERT(f->ilf_size == 3 + hasdata);
356 printf(_(" ATTR FORK BTREE inode data:\n"));
357 if (print_inode && print_data)
358 xlog_recover_print_data(
359 item->ri_buf[attr_index].i_addr,
360 item->ri_buf[attr_index].i_len);
361 break;
362 case XFS_ILOG_ADATA:
363 ASSERT(f->ilf_size == 3 + hasdata);
364 printf(_(" ATTR FORK LOCAL inode data:\n"));
365 if (print_inode && print_data)
366 xlog_recover_print_data(
367 item->ri_buf[attr_index].i_addr,
368 item->ri_buf[attr_index].i_len);
369 break;
370 default:
371 xlog_panic("%s: illegal inode log flag", __FUNCTION__);
372 }
373 }
374 }
375
376 STATIC void
377 xlog_recover_print_efd(
378 xlog_recover_item_t *item)
379 {
380 xfs_efd_log_format_t *f;
381
382 f = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
383 /*
384 * An xfs_efd_log_format structure contains a variable length array
385 * as the last field.
386 * Each element is of size xfs_extent_32_t or xfs_extent_64_t.
387 * However, the extents are never used and won't be printed.
388 */
389 printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"),
390 f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id);
391 }
392
393
394 STATIC void
395 xlog_recover_print_efi(
396 xlog_recover_item_t *item)
397 {
398 xfs_efi_log_format_t *f, *src_f;
399 xfs_extent_t *ex;
400 int i;
401 uint src_len, dst_len;
402
403 src_f = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
404 src_len = item->ri_buf[0].i_len;
405 /*
406 * An xfs_efi_log_format structure contains a variable length array
407 * as the last field.
408 * Each element is of size xfs_extent_32_t or xfs_extent_64_t.
409 * Need to convert to native format.
410 */
411 dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t);
412 if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) {
413 fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname);
414 exit(1);
415 }
416 if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) {
417 free(f);
418 return;
419 }
420
421 printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"),
422 f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id);
423 ex = f->efi_extents;
424 printf(" ");
425 for (i=0; i< f->efi_nextents; i++) {
426 printf("(s: 0x%llx, l: %d) ",
427 (unsigned long long)ex->ext_start, ex->ext_len);
428 if (i % 4 == 3)
429 printf("\n");
430 ex++;
431 }
432 if (i % 4 != 0)
433 printf("\n");
434 free(f);
435 }
436
437 STATIC void
438 xlog_recover_print_icreate(
439 struct xlog_recover_item *item)
440 {
441 struct xfs_icreate_log *icl;
442
443 icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr;
444
445 printf(_(" ICR: #ag: %d agbno: 0x%x len: %d\n"
446 " cnt: %d isize: %d gen: 0x%x\n"),
447 be32_to_cpu(icl->icl_ag), be32_to_cpu(icl->icl_agbno),
448 be32_to_cpu(icl->icl_length), be32_to_cpu(icl->icl_count),
449 be32_to_cpu(icl->icl_isize), be32_to_cpu(icl->icl_gen));
450 }
451
452 void
453 xlog_recover_print_logitem(
454 xlog_recover_item_t *item)
455 {
456 switch (ITEM_TYPE(item)) {
457 case XFS_LI_BUF:
458 xlog_recover_print_buffer(item);
459 break;
460 case XFS_LI_ICREATE:
461 xlog_recover_print_icreate(item);
462 break;
463 case XFS_LI_INODE:
464 xlog_recover_print_inode(item);
465 break;
466 case XFS_LI_EFD:
467 xlog_recover_print_efd(item);
468 break;
469 case XFS_LI_EFI:
470 xlog_recover_print_efi(item);
471 break;
472 case XFS_LI_DQUOT:
473 xlog_recover_print_dquot(item);
474 break;
475 case XFS_LI_QUOTAOFF:
476 xlog_recover_print_quotaoff(item);
477 break;
478 default:
479 printf(_("xlog_recover_print_logitem: illegal type\n"));
480 break;
481 }
482 }
483
484 void
485 xlog_recover_print_item(
486 xlog_recover_item_t *item)
487 {
488 int i;
489
490 switch (ITEM_TYPE(item)) {
491 case XFS_LI_BUF:
492 printf("BUF");
493 break;
494 case XFS_LI_ICREATE:
495 printf("ICR");
496 break;
497 case XFS_LI_INODE:
498 printf("INO");
499 break;
500 case XFS_LI_EFD:
501 printf("EFD");
502 break;
503 case XFS_LI_EFI:
504 printf("EFI");
505 break;
506 case XFS_LI_DQUOT:
507 printf("DQ ");
508 break;
509 case XFS_LI_QUOTAOFF:
510 printf("QOFF");
511 break;
512 default:
513 cmn_err(CE_PANIC, _("%s: illegal type"), __FUNCTION__);
514 break;
515 }
516
517 /* type isn't filled in yet
518 printf(_("ITEM: type: %d cnt: %d total: %d "),
519 item->ri_type, item->ri_cnt, item->ri_total);
520 */
521 printf(_(": cnt:%d total:%d "), item->ri_cnt, item->ri_total);
522 for (i=0; i<item->ri_cnt; i++) {
523 printf(_("a:0x%lx len:%d "),
524 (long)item->ri_buf[i].i_addr, item->ri_buf[i].i_len);
525 }
526 printf("\n");
527 xlog_recover_print_logitem(item);
528 }
529
530 void
531 xlog_recover_print_trans(
532 xlog_recover_t *trans,
533 struct list_head *itemq,
534 int print)
535 {
536 xlog_recover_item_t *item;
537
538 if (print < 3)
539 return;
540
541 print_xlog_record_line();
542 xlog_recover_print_trans_head(trans);
543 list_for_each_entry(item, itemq, ri_list)
544 xlog_recover_print_item(item);
545 }