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