Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include <ctype.h>
6 : #include <string.h>
7 : #include <inttypes.h>
8 : #include <sys/types.h>
9 : #include <sys/stat.h>
10 : #include <fcntl.h>
11 : #include <unistd.h>
12 : #include <errno.h>
13 : #include <curses.h>
14 : #include <term.h>
15 : #include <signal.h>
16 : #include <sys/ioctl.h>
17 : #include <sys/mount.h>
18 : #include <dirent.h>
19 :
20 : #include "copyright.cf"
21 :
22 : #include "hexedit.h"
23 : #include "libgfs2.h"
24 : #include "extended.h"
25 : #include "gfs2hex.h"
26 : #include "journal.h"
27 :
28 : /**
29 : * find_journal_block - figure out where a journal starts, given the name
30 : * Returns: journal block number, changes j_size to the journal size
31 : */
32 2 : uint64_t find_journal_block(const char *journal, uint64_t *j_size)
33 : {
34 : int journal_num;
35 2 : uint64_t jindex_block, jblock = 0;
36 : struct lgfs2_buffer_head *jindex_bh, *j_bh;
37 : struct gfs2_dinode *jdi;
38 :
39 2 : journal_num = atoi(journal + 7);
40 2 : if (journal_num < 0)
41 0 : return 0;
42 :
43 2 : jindex_block = masterblock("jindex");
44 2 : jindex_bh = lgfs2_bread(&sbd, jindex_block);
45 2 : di = (struct gfs2_dinode *)jindex_bh->b_data;
46 2 : do_dinode_extended(jindex_bh->b_data);
47 2 : if (journal_num > indirect->ii[0].dirents - 2) {
48 0 : lgfs2_brelse(jindex_bh);
49 0 : return 0;
50 : }
51 2 : jblock = indirect->ii[0].dirent[journal_num + 2].inum.in_addr;
52 2 : j_bh = lgfs2_bread(&sbd, jblock);
53 2 : jdi = (struct gfs2_dinode *)j_bh->b_data;
54 2 : *j_size = be64_to_cpu(jdi->di_size);
55 2 : lgfs2_brelse(j_bh);
56 2 : lgfs2_brelse(jindex_bh);
57 2 : return jblock;
58 : }
59 :
60 0 : static void check_journal_wrap(uint64_t seq, uint64_t *highest_seq)
61 : {
62 0 : if (seq < *highest_seq) {
63 0 : print_gfs2("------------------------------------------------"
64 : "------------------------------------------------");
65 0 : eol(0);
66 0 : print_gfs2("Journal wrapped here.");
67 0 : eol(0);
68 0 : print_gfs2("------------------------------------------------"
69 : "------------------------------------------------");
70 0 : eol(0);
71 : }
72 0 : *highest_seq = seq;
73 0 : }
74 :
75 : /**
76 : * fsck_readi - same as libgfs2's lgfs2_readi, but sets absolute block #
77 : * of the first bit of data read.
78 : */
79 0 : static int fsck_readi(struct lgfs2_inode *ip, void *rbuf, uint64_t roffset,
80 : unsigned int size, uint64_t *abs_block)
81 : {
82 : struct lgfs2_sbd *sdp;
83 : struct lgfs2_buffer_head *lbh;
84 : uint64_t lblock, dblock;
85 : unsigned int o;
86 0 : uint32_t extlen = 0;
87 : unsigned int amount;
88 0 : int not_new = 0;
89 : int isdir;
90 0 : int copied = 0;
91 :
92 0 : if (ip == NULL)
93 0 : return 0;
94 0 : sdp = ip->i_sbd;
95 0 : isdir = !!(S_ISDIR(ip->i_mode));
96 0 : *abs_block = 0;
97 0 : if (roffset >= ip->i_size)
98 0 : return 0;
99 0 : if ((roffset + size) > ip->i_size)
100 0 : size = ip->i_size - roffset;
101 0 : if (!size)
102 0 : return 0;
103 0 : if (isdir) {
104 0 : o = roffset % sdp->sd_jbsize;
105 0 : lblock = roffset / sdp->sd_jbsize;
106 : } else {
107 0 : lblock = roffset >> sdp->sd_bsize_shift;
108 0 : o = roffset & (sdp->sd_bsize - 1);
109 : }
110 :
111 0 : if (!ip->i_height) /* inode_is_stuffed */
112 0 : o += sizeof(struct gfs2_dinode);
113 0 : else if (isdir)
114 0 : o += sizeof(struct gfs2_meta_header);
115 :
116 0 : while (copied < size) {
117 0 : amount = size - copied;
118 0 : if (amount > sdp->sd_bsize - o)
119 0 : amount = sdp->sd_bsize - o;
120 0 : if (!extlen)
121 0 : if (lgfs2_block_map(ip, lblock, ¬_new, &dblock, &extlen, FALSE))
122 0 : exit(1);
123 0 : if (dblock) {
124 0 : lbh = lgfs2_bread(sdp, dblock);
125 0 : if (*abs_block == 0)
126 0 : *abs_block = lbh->b_blocknr;
127 0 : dblock++;
128 0 : extlen--;
129 : } else
130 0 : lbh = NULL;
131 0 : if (lbh) {
132 0 : memcpy(rbuf, lbh->b_data + o, amount);
133 0 : lgfs2_brelse(lbh);
134 : } else {
135 0 : memset(rbuf, 0, amount);
136 : }
137 0 : copied += amount;
138 0 : lblock++;
139 0 : o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
140 : }
141 0 : return copied;
142 : }
143 :
144 : /**
145 : * ld_is_pertinent - determine if a log descriptor is pertinent
146 : *
147 : * This function checks a log descriptor buffer to see if it contains
148 : * references to a given traced block, or its rgrp bitmap block.
149 : */
150 0 : static int ld_is_pertinent(const __be64 *b, const char *end, uint64_t tblk,
151 : struct lgfs2_rgrp_tree *rgd, uint64_t bitblk)
152 : {
153 0 : const __be64 *blk = b;
154 :
155 0 : if (!tblk)
156 0 : return 1;
157 :
158 0 : while (*blk && (char *)blk < end) {
159 0 : if (be64_to_cpu(*blk) == tblk || be64_to_cpu(*blk) == bitblk)
160 0 : return 1;
161 0 : blk++;
162 : }
163 0 : return 0;
164 : }
165 :
166 : /**
167 : * print_ld_blks - print all blocks given in a log descriptor
168 : * returns: the number of block numbers it printed
169 : */
170 0 : static int print_ld_blks(const __be64 *b, const char *end, int start_line,
171 : uint64_t tblk, uint64_t *tblk_off, uint64_t bitblk,
172 : struct lgfs2_rgrp_tree *rgd, uint64_t abs_block, int prnt,
173 : uint64_t *bblk_off, int is_meta_ld)
174 : {
175 0 : int bcount = 0, found_tblk = 0, found_bblk = 0;
176 : static char str[256];
177 : struct lgfs2_buffer_head *j_bmap_bh;
178 :
179 0 : if (tblk_off)
180 0 : *tblk_off = 0;
181 0 : if (bblk_off)
182 0 : *bblk_off = 0;
183 0 : while (*b && (char *)b < end) {
184 0 : if (!termlines ||
185 0 : (print_entry_ndx >= start_row[dmode] &&
186 0 : ((print_entry_ndx - start_row[dmode])+1) *
187 0 : lines_per_row[dmode] <= termlines - start_line - 2)) {
188 0 : if (prnt && bcount && bcount % 4 == 0) {
189 0 : eol(0);
190 0 : print_gfs2(" ");
191 : }
192 0 : bcount++;
193 0 : if (prnt) {
194 0 : if (is_meta_ld) {
195 0 : j_bmap_bh = lgfs2_bread(&sbd, abs_block +
196 : bcount);
197 0 : sprintf(str, "0x%"PRIx64" %2s",
198 : be64_to_cpu(*b),
199 0 : mtypes[lgfs2_get_block_type(j_bmap_bh->b_data)]);
200 0 : lgfs2_brelse(j_bmap_bh);
201 : } else {
202 0 : sprintf(str, "0x%"PRIx64, be64_to_cpu(*b));
203 : }
204 0 : print_gfs2("%-18.18s ", str);
205 : }
206 0 : if (!found_tblk && tblk_off)
207 0 : (*tblk_off)++;
208 0 : if (!found_bblk && bblk_off)
209 0 : (*bblk_off)++;
210 0 : if (tblk && (be64_to_cpu(*b) == tblk)) {
211 0 : found_tblk = 1;
212 0 : print_gfs2("<-------------------------0x%"PRIx64" ", tblk);
213 0 : eol(18 * (bcount % 4) + 1);
214 0 : print_gfs2(" ");
215 : }
216 0 : if (tblk && rgd && (be64_to_cpu(*b) == bitblk)) {
217 0 : int type, bmap = 0;
218 : uint64_t o;
219 : char *save_ptr;
220 :
221 0 : found_bblk = 1;
222 0 : print_gfs2("<-------------------------");
223 0 : if (is_meta_ld) {
224 0 : o = tblk - rgd->rt_data0;
225 0 : if (o >= ((uint64_t)rgd->rt_bits->bi_start +
226 0 : rgd->rt_bits->bi_len) *
227 : GFS2_NBBY)
228 0 : o += (sizeof(struct gfs2_rgrp) -
229 : sizeof(struct gfs2_meta_header))
230 : * GFS2_NBBY;
231 0 : bmap = o / sbd.sd_blocks_per_bitmap;
232 0 : save_ptr = rgd->rt_bits[bmap].bi_data;
233 0 : j_bmap_bh = lgfs2_bread(&sbd, abs_block +
234 : bcount);
235 0 : rgd->rt_bits[bmap].bi_data = j_bmap_bh->b_data;
236 0 : type = lgfs2_get_bitmap(&sbd, tblk, rgd);
237 0 : lgfs2_brelse(j_bmap_bh);
238 0 : if (type < 0) {
239 0 : perror("Error printing log descriptor blocks");
240 0 : exit(1);
241 : }
242 0 : rgd->rt_bits[bmap].bi_data = save_ptr;
243 0 : print_gfs2("bit for blk 0x%"PRIx64" is %d (%s)",
244 : tblk, type,
245 : allocdesc[type]);
246 : } else {
247 0 : print_gfs2("bitmap for blk 0x%"PRIx64" was revoked",
248 : tblk);
249 : }
250 0 : eol(18 * (bcount % 4) + 1);
251 0 : print_gfs2(" ");
252 : }
253 : }
254 0 : b++;
255 : }
256 0 : if (prnt)
257 0 : eol(0);
258 0 : if (tblk_off && (!found_tblk || !is_meta_ld))
259 0 : *tblk_off = 0;
260 0 : if (bblk_off && (!found_bblk || !is_meta_ld))
261 0 : *bblk_off = 0;
262 0 : return bcount;
263 : }
264 :
265 0 : static int is_wrap_pt(void *buf, uint64_t *highest_seq)
266 : {
267 0 : const struct lgfs2_metadata *mtype = get_block_type(buf);
268 :
269 0 : if (mtype != NULL && mtype->mh_type == GFS2_METATYPE_LH) {
270 0 : struct gfs2_log_header *lh = buf;
271 : uint64_t seq;
272 :
273 0 : seq = be64_to_cpu(lh->lh_sequence);
274 0 : if (seq < *highest_seq)
275 0 : return 1;
276 0 : *highest_seq = seq;
277 : }
278 0 : return 0;
279 : }
280 :
281 : /**
282 : * find_wrap_pt - figure out where a journal wraps
283 : * Returns: The wrap point, in bytes
284 : */
285 0 : static uint64_t find_wrap_pt(struct lgfs2_inode *ji, char *jbuf, uint64_t jblock, uint64_t j_size)
286 : {
287 0 : uint64_t jb = 0;
288 0 : uint64_t highest_seq = 0;
289 :
290 0 : for (jb = 0; jb < j_size; jb += sbd.sd_bsize) {
291 0 : int found = 0;
292 : int copied;
293 : uint64_t abs_block;
294 :
295 0 : copied = fsck_readi(ji, jbuf, jb, sbd.sd_bsize, &abs_block);
296 0 : if (!copied) /* end of file */
297 0 : break;
298 0 : found = is_wrap_pt(jbuf, &highest_seq);
299 0 : if (found)
300 0 : return jb;
301 : }
302 0 : return 0;
303 : }
304 :
305 : /**
306 : * process_ld - process a log descriptor
307 : */
308 0 : static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
309 : uint64_t jb, char *buf, int tblk,
310 : uint64_t *tblk_off, uint64_t bitblk,
311 : struct lgfs2_rgrp_tree *rgd, int *prnt, uint64_t *bblk_off)
312 : {
313 : __be64 *b;
314 0 : struct gfs2_log_descriptor *ld = (void *)buf;
315 0 : int ltndx, is_meta_ld = 0;
316 0 : int ld_blocks = 0;
317 0 : uint32_t ld_type = be32_to_cpu(ld->ld_type);
318 0 : uint32_t ld_length = be32_to_cpu(ld->ld_length);
319 0 : uint32_t ld_data1 = be32_to_cpu(ld->ld_data1);
320 0 : uint32_t logtypes[6] = {
321 : GFS2_LOG_DESC_METADATA,
322 : GFS2_LOG_DESC_REVOKE,
323 : GFS2_LOG_DESC_JDATA,
324 : 0, 0, 0
325 : };
326 0 : const char *logtypestr[6] = {
327 : "Metadata",
328 : "Revoke",
329 : "Jdata",
330 : "Unknown",
331 : "Unknown",
332 : "Unknown"
333 : };
334 0 : b = (__be64 *)(buf + sizeof(struct gfs2_log_descriptor));
335 0 : *prnt = ld_is_pertinent(b, (buf + sbd.sd_bsize), tblk, rgd, bitblk);
336 :
337 0 : if (*prnt) {
338 0 : print_gfs2("0x%"PRIx64" (j+%4"PRIx64"): Log descriptor, ",
339 0 : abs_block, ((jb + wrappt) % j_size) / sbd.sd_bsize);
340 0 : print_gfs2("type %"PRIu32" ", ld_type);
341 :
342 0 : for (ltndx = 0;; ltndx++) {
343 0 : if (ld_type == logtypes[ltndx] ||
344 0 : logtypes[ltndx] == 0)
345 : break;
346 : }
347 0 : print_gfs2("(%s) ", logtypestr[ltndx]);
348 0 : print_gfs2("len:%"PRIu32", data1: %"PRIu32, ld_length, ld_data1);
349 0 : eol(0);
350 0 : print_gfs2(" ");
351 : }
352 0 : ld_blocks = ld_data1;
353 0 : if (ld_type == GFS2_LOG_DESC_METADATA)
354 0 : is_meta_ld = 1;
355 0 : ld_blocks -= print_ld_blks(b, (buf + sbd.sd_bsize), line, tblk, tblk_off,
356 : bitblk, rgd, abs_block, *prnt, bblk_off,
357 : is_meta_ld);
358 :
359 0 : return ld_blocks;
360 : }
361 :
362 : /**
363 : * meta_has_ref - check if a metadata block references a given block
364 : */
365 0 : static int meta_has_ref(uint64_t abs_block, int tblk)
366 : {
367 : const struct lgfs2_metadata *mtype;
368 : struct lgfs2_buffer_head *mbh;
369 0 : int structlen = 0, has_ref = 0;
370 : __be64 *b;
371 : struct gfs2_dinode *dinode;
372 :
373 0 : mbh = lgfs2_bread(&sbd, abs_block);
374 0 : mtype = get_block_type(mbh->b_data);
375 0 : if (mtype != NULL) {
376 0 : structlen = mtype->size;
377 0 : if (mtype->mh_type == GFS2_METATYPE_DI) {
378 0 : dinode = (struct gfs2_dinode *)mbh->b_data;
379 0 : if (be64_to_cpu(dinode->di_eattr) == tblk)
380 0 : has_ref = 1;
381 : }
382 : }
383 0 : b = (__be64 *)(mbh->b_data + structlen);
384 0 : while (!has_ref && mtype && (char *)b < mbh->b_data + sbd.sd_bsize) {
385 0 : if (be64_to_cpu(*b) == tblk)
386 0 : has_ref = 1;
387 0 : b++;
388 : }
389 0 : lgfs2_brelse(mbh);
390 0 : return has_ref;
391 : }
392 :
393 :
394 : /**
395 : * get_ldref - get a log descriptor reference block, given a block number
396 : *
397 : * Note that we can't pass in abs_block here, because journal wrap may
398 : * mean that the block we're interested in, in the journal, is before the
399 : * log descriptor that holds the reference we need.
400 : */
401 0 : static uint64_t get_ldref(uint64_t abs_ld, int offset_from_ld)
402 : {
403 : struct lgfs2_buffer_head *jbh;
404 : uint64_t refblk;
405 : __be64 *b;
406 :
407 0 : jbh = lgfs2_bread(&sbd, abs_ld);
408 0 : b = (__be64 *)(jbh->b_data + sizeof(struct gfs2_log_descriptor));
409 0 : b += offset_from_ld - 1;
410 0 : refblk = be64_to_cpu(*b);
411 0 : lgfs2_brelse(jbh);
412 0 : return refblk;
413 : }
414 :
415 0 : static void display_log_header(void *buf, uint64_t *highest_seq, uint64_t abs_block, uint64_t jb, uint64_t j_size)
416 : {
417 : const struct lgfs2_metafield *lh_flags_field;
418 : const struct lgfs2_metadata *mtype;
419 0 : struct gfs2_log_header *lh = buf;
420 0 : uint64_t jlb = (jb % j_size) / sbd.sd_bsize;
421 0 : uint64_t seq = be64_to_cpu(lh->lh_sequence);
422 0 : uint32_t tail = be32_to_cpu(lh->lh_tail);
423 0 : uint32_t blkn = be32_to_cpu(lh->lh_blkno);
424 0 : uint64_t tot = be64_to_cpu(lh->lh_local_total);
425 0 : uint64_t fr = be64_to_cpu(lh->lh_local_free);
426 0 : uint64_t ndi = be64_to_cpu(lh->lh_local_dinodes);
427 : char flags_str[256];
428 :
429 0 : mtype = &lgfs2_metadata[LGFS2_MT_GFS2_LOG_HEADER];
430 0 : lh_flags_field = &mtype->fields[6]; /* lh_flags is the 7th field in the struct */
431 0 : check_journal_wrap(be64_to_cpu(lh->lh_sequence), highest_seq);
432 0 : lgfs2_field_str(flags_str, sizeof(flags_str), buf, lh_flags_field, (dmode == HEX_MODE));
433 :
434 0 : print_gfs2("0x%"PRIx64" (j+%4"PRIx64"): Log header: seq: 0x%"PRIx64", "
435 : "tail: 0x%"PRIx32", blk: 0x%"PRIx32", tot: 0x%"PRIx64", "
436 : "fr: 0x%"PRIx64", di: 0x%"PRIx64" [%s]",
437 : abs_block, jlb, seq, tail, blkn, tot, fr, ndi, flags_str);
438 0 : }
439 :
440 : /**
441 : * dump_journal - dump a journal file's contents.
442 : * @journal: name of the journal to dump
443 : * @tblk: block number to trace in the journals
444 : *
445 : * This function dumps the contents of a journal. If a trace block is specified
446 : * then only information printed is: (1) log descriptors that reference that
447 : * block, (2) metadata in the journal that references the block, or (3)
448 : * rgrp bitmaps that reference that block's allocation bit status.
449 : */
450 0 : void dump_journal(const char *journal, uint64_t tblk)
451 : {
452 : const struct lgfs2_metadata *mtype;
453 0 : struct lgfs2_buffer_head *j_bh = NULL;
454 0 : uint64_t jblock, j_size, jb, abs_block, saveblk, wrappt = 0;
455 : int start_line, journal_num;
456 0 : struct lgfs2_inode *j_inode = NULL;
457 0 : int ld_blocks = 0, offset_from_ld = 0;
458 0 : uint64_t tblk_off = 0, bblk_off = 0, bitblk = 0;
459 0 : uint64_t highest_seq = 0;
460 0 : char *jbuf = NULL;
461 0 : char *buf = NULL;
462 0 : struct lgfs2_rgrp_tree *rgd = NULL;
463 0 : uint64_t abs_ld = 0;
464 :
465 0 : mtype = lgfs2_find_mtype(GFS2_METATYPE_LH);
466 :
467 0 : start_line = line;
468 0 : lines_per_row[dmode] = 1;
469 0 : journal_num = atoi(journal + 7);
470 0 : print_gfs2("Dumping journal #%d.", journal_num);
471 0 : if (tblk) {
472 0 : dmode = HEX_MODE;
473 0 : print_gfs2(" Tracing block 0x%"PRIx64, tblk);
474 : }
475 0 : eol(0);
476 0 : jblock = find_journal_block(journal, &j_size);
477 0 : if (!jblock)
478 0 : return;
479 :
480 0 : j_bh = lgfs2_bread(&sbd, jblock);
481 0 : j_inode = lgfs2_inode_get(&sbd, j_bh);
482 0 : if (j_inode == NULL) {
483 0 : fprintf(stderr, "Out of memory\n");
484 0 : exit(-1);
485 : }
486 0 : jbuf = malloc(sbd.sd_bsize);
487 0 : if (jbuf == NULL) {
488 0 : fprintf(stderr, "Out of memory\n");
489 0 : exit(-1);
490 : }
491 :
492 0 : if (tblk) {
493 : uint64_t wp;
494 :
495 0 : rgd = lgfs2_blk2rgrpd(&sbd, tblk);
496 0 : if (!rgd) {
497 0 : print_gfs2("Can't locate the rgrp for block 0x%"PRIx64,
498 : tblk);
499 0 : eol(0);
500 : } else {
501 : uint64_t o;
502 0 : int bmap = 0;
503 :
504 0 : print_gfs2("rgd: 0x%"PRIx64" for 0x%"PRIx32", ", rgd->rt_addr,
505 : rgd->rt_length);
506 0 : o = tblk - rgd->rt_data0;
507 0 : if (o >= (rgd->rt_bits->bi_start +
508 0 : rgd->rt_bits->bi_len) * (uint64_t)GFS2_NBBY)
509 0 : o += (sizeof(struct gfs2_rgrp) -
510 : sizeof(struct gfs2_meta_header))
511 : * GFS2_NBBY;
512 0 : bmap = o / sbd.sd_blocks_per_bitmap;
513 0 : bitblk = rgd->rt_addr + bmap;
514 0 : print_gfs2("bitmap: %d, bitblk: 0x%"PRIx64, bmap, bitblk);
515 0 : eol(0);
516 : }
517 :
518 0 : wrappt = find_wrap_pt(j_inode, jbuf, jblock, j_size);
519 0 : wp = wrappt / sbd.sd_bsize;
520 0 : print_gfs2("Starting at journal wrap block: 0x%"PRIx64" (j + 0x%"PRIx64")",
521 : jblock + wp, wp);
522 0 : eol(0);
523 : }
524 :
525 0 : for (jb = 0; jb < j_size; jb += sbd.sd_bsize) {
526 0 : int is_pertinent = 1;
527 0 : uint32_t block_type = 0;
528 0 : int error = fsck_readi(j_inode, (void *)jbuf,
529 0 : ((jb + wrappt) % j_size),
530 : sbd.sd_bsize, &abs_block);
531 0 : if (!error) /* end of file */
532 0 : break;
533 0 : buf = jbuf;
534 0 : offset_from_ld++;
535 0 : mtype = get_block_type(buf);
536 0 : if (mtype != NULL)
537 0 : block_type = mtype->mh_type;
538 :
539 0 : if (block_type == GFS2_METATYPE_LD) {
540 0 : ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
541 : buf, tblk, &tblk_off,
542 : bitblk, rgd, &is_pertinent,
543 : &bblk_off);
544 0 : offset_from_ld = 0;
545 0 : abs_ld = abs_block;
546 0 : } else if (!tblk && block_type == GFS2_METATYPE_LH) {
547 0 : display_log_header(buf, &highest_seq, abs_block, jb + wrappt, j_size);
548 0 : eol(0);
549 0 : } else if ((ld_blocks > 0) && (block_type == GFS2_METATYPE_LB)) {
550 0 : __be64 *b = (__be64 *)(buf + sizeof(struct gfs2_meta_header));
551 :
552 0 : print_gfs2("0x%"PRIx64" (j+%4"PRIx64"): Log descriptor"
553 : " continuation block", abs_block,
554 0 : ((jb + wrappt) % j_size) / sbd.sd_bsize);
555 0 : eol(0);
556 0 : print_gfs2(" ");
557 0 : ld_blocks -= print_ld_blks(b, (buf + sbd.sd_bsize), start_line,
558 : tblk, &tblk_off, 0, rgd, 0, 1, NULL, 0);
559 0 : } else if (block_type == 0) {
560 0 : continue;
561 : }
562 : /* Check if this metadata block references the block we're
563 : trying to trace. */
564 0 : if (details || (tblk && ((is_pertinent &&
565 0 : ((tblk_off && offset_from_ld == tblk_off) ||
566 0 : (bblk_off && offset_from_ld == bblk_off))) ||
567 0 : meta_has_ref(abs_block, tblk)))) {
568 0 : uint64_t ref_blk = 0;
569 :
570 0 : saveblk = block;
571 0 : block = abs_block;
572 0 : if (tblk && !details) {
573 0 : ref_blk = get_ldref(abs_ld, offset_from_ld);
574 0 : display(0, 1, tblk, ref_blk);
575 : } else {
576 0 : display(0, 0, 0, 0);
577 : }
578 0 : block = saveblk;
579 : }
580 : }
581 0 : if (j_inode != NULL)
582 0 : lgfs2_inode_put(&j_inode);
583 0 : lgfs2_brelse(j_bh);
584 0 : blockhist = -1; /* So we don't print anything else */
585 0 : free(jbuf);
586 0 : if (!termlines)
587 0 : fflush(stdout);
588 : }
|