• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * dump.c
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *             http://www.samsung.com/
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #include <inttypes.h>
12 
13 #include "fsck.h"
14 #include <locale.h>
15 
16 #define BUF_SZ	80
17 
18 const char *seg_type_name[SEG_TYPE_MAX + 1] = {
19 	"SEG_TYPE_DATA",
20 	"SEG_TYPE_CUR_DATA",
21 	"SEG_TYPE_NODE",
22 	"SEG_TYPE_CUR_NODE",
23 	"SEG_TYPE_NONE",
24 };
25 
nat_dump(struct f2fs_sb_info * sbi)26 void nat_dump(struct f2fs_sb_info *sbi)
27 {
28 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
29 	struct f2fs_nm_info *nm_i = NM_I(sbi);
30 	struct f2fs_nat_block *nat_block;
31 	struct f2fs_node *node_block;
32 	u32 nr_nat_blks, nid;
33 	pgoff_t block_off;
34 	pgoff_t block_addr;
35 	char buf[BUF_SZ];
36 	int seg_off;
37 	int fd, ret, pack;
38 	unsigned int i;
39 
40 	nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1);
41 	node_block = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
42 	ASSERT(nat_block);
43 
44 	nr_nat_blks = get_sb(segment_count_nat) <<
45 				(sbi->log_blocks_per_seg - 1);
46 
47 	fd = open("dump_nat", O_CREAT|O_WRONLY|O_TRUNC, 0666);
48 	ASSERT(fd >= 0);
49 
50 	for (block_off = 0; block_off < nr_nat_blks; pack = 1, block_off++) {
51 
52 		seg_off = block_off >> sbi->log_blocks_per_seg;
53 		block_addr = (pgoff_t)(nm_i->nat_blkaddr +
54 			(seg_off << sbi->log_blocks_per_seg << 1) +
55 			(block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
56 
57 		if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) {
58 			block_addr += sbi->blocks_per_seg;
59 			pack = 2;
60 		}
61 
62 		ret = dev_read_block(nat_block, block_addr);
63 		ASSERT(ret >= 0);
64 
65 		nid = block_off * NAT_ENTRY_PER_BLOCK;
66 		for (i = 0; i < NAT_ENTRY_PER_BLOCK; i++) {
67 			struct f2fs_nat_entry raw_nat;
68 			struct node_info ni;
69 			ni.nid = nid + i;
70 
71 			if(nid + i  == 0 || nid + i  == 1 || nid + i == 2 )
72 				continue;
73 			if (lookup_nat_in_journal(sbi, nid + i,
74 							&raw_nat) >= 0) {
75 				node_info_from_raw_nat(&ni, &raw_nat);
76 				ret = dev_read_block(node_block, ni.blk_addr);
77 				ASSERT(ret >= 0);
78 				if (ni.blk_addr != 0x0) {
79 					memset(buf, 0, BUF_SZ);
80 					snprintf(buf, BUF_SZ,
81 						"nid:%5u\tino:%5u\toffset:%5u"
82 						"\tblkaddr:%10u\tpack:%d\n",
83 						ni.nid, ni.ino,
84 						le32_to_cpu(node_block->footer.flag) >>
85 							OFFSET_BIT_SHIFT,
86 						ni.blk_addr, pack);
87 					ret = write(fd, buf, strlen(buf));
88 					ASSERT(ret >= 0);
89 				}
90 			} else {
91 				node_info_from_raw_nat(&ni,
92 						&nat_block->entries[i]);
93 				if (ni.blk_addr == 0)
94 					continue;
95 
96 				ret = dev_read_block(node_block, ni.blk_addr);
97 				ASSERT(ret >= 0);
98 				memset(buf, 0, BUF_SZ);
99 				snprintf(buf, BUF_SZ,
100 					"nid:%5u\tino:%5u\toffset:%5u"
101 					"\tblkaddr:%10u\tpack:%d\n",
102 					ni.nid, ni.ino,
103 					le32_to_cpu(node_block->footer.flag) >>
104 						OFFSET_BIT_SHIFT,
105 					ni.blk_addr, pack);
106 				ret = write(fd, buf, strlen(buf));
107 				ASSERT(ret >= 0);
108 			}
109 		}
110 	}
111 
112 	free(nat_block);
113 	free(node_block);
114 
115 	close(fd);
116 }
117 
sit_dump(struct f2fs_sb_info * sbi,unsigned int start_sit,unsigned int end_sit)118 void sit_dump(struct f2fs_sb_info *sbi, unsigned int start_sit,
119 					unsigned int end_sit)
120 {
121 	struct seg_entry *se;
122 	struct sit_info *sit_i = SIT_I(sbi);
123 	unsigned int segno;
124 	char buf[BUF_SZ];
125 	u32 free_segs = 0;;
126 	u64 valid_blocks = 0;
127 	int ret;
128 	int fd, i;
129 	unsigned int offset;
130 
131 	fd = open("dump_sit", O_CREAT|O_WRONLY|O_TRUNC, 0666);
132 	ASSERT(fd >= 0);
133 
134 	snprintf(buf, BUF_SZ, "segment_type(0:HD, 1:WD, 2:CD, "
135 						"3:HN, 4:WN, 5:CN)\n");
136 	ret = write(fd, buf, strlen(buf));
137 	ASSERT(ret >= 0);
138 
139 	for (segno = start_sit; segno < end_sit; segno++) {
140 		se = get_seg_entry(sbi, segno);
141 		offset = SIT_BLOCK_OFFSET(sit_i, segno);
142 		memset(buf, 0, BUF_SZ);
143 		snprintf(buf, BUF_SZ,
144 		"\nsegno:%8u\tvblocks:%3u\tseg_type:%d\tsit_pack:%d\n\n",
145 			segno, se->valid_blocks, se->type,
146 			f2fs_test_bit(offset, sit_i->sit_bitmap) ? 2 : 1);
147 
148 		ret = write(fd, buf, strlen(buf));
149 		ASSERT(ret >= 0);
150 
151 		if (se->valid_blocks == 0x0) {
152 			free_segs++;
153 			continue;
154 		}
155 
156 		ASSERT(se->valid_blocks <= 512);
157 		valid_blocks += se->valid_blocks;
158 
159 		for (i = 0; i < 64; i++) {
160 			memset(buf, 0, BUF_SZ);
161 			snprintf(buf, BUF_SZ, "  %02x",
162 					*(se->cur_valid_map + i));
163 			ret = write(fd, buf, strlen(buf));
164 			ASSERT(ret >= 0);
165 
166 			if ((i + 1) % 16 == 0) {
167 				snprintf(buf, BUF_SZ, "\n");
168 				ret = write(fd, buf, strlen(buf));
169 				ASSERT(ret >= 0);
170 			}
171 		}
172 	}
173 
174 	memset(buf, 0, BUF_SZ);
175 	snprintf(buf, BUF_SZ,
176 		"valid_blocks:[0x%" PRIx64 "]\tvalid_segs:%d\t free_segs:%d\n",
177 			valid_blocks,
178 			SM_I(sbi)->main_segments - free_segs,
179 			free_segs);
180 	ret = write(fd, buf, strlen(buf));
181 	ASSERT(ret >= 0);
182 
183 	close(fd);
184 }
185 
ssa_dump(struct f2fs_sb_info * sbi,int start_ssa,int end_ssa)186 void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa)
187 {
188 	struct f2fs_summary_block *sum_blk;
189 	char buf[BUF_SZ];
190 	int segno, i, ret;
191 	int fd;
192 
193 	fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666);
194 	ASSERT(fd >= 0);
195 
196 	snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * "
197 				" 0x200 + offset\n",
198 				sbi->sm_info->main_blkaddr);
199 	ret = write(fd, buf, strlen(buf));
200 	ASSERT(ret >= 0);
201 
202 	for (segno = start_ssa; segno < end_ssa; segno++) {
203 		sum_blk = get_sum_block(sbi, segno, &ret);
204 
205 		memset(buf, 0, BUF_SZ);
206 		switch (ret) {
207 		case SEG_TYPE_CUR_NODE:
208 			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno);
209 			break;
210 		case SEG_TYPE_CUR_DATA:
211 			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno);
212 			break;
213 		case SEG_TYPE_NODE:
214 			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno);
215 			break;
216 		case SEG_TYPE_DATA:
217 			snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno);
218 			break;
219 		}
220 		ret = write(fd, buf, strlen(buf));
221 		ASSERT(ret >= 0);
222 
223 		for (i = 0; i < ENTRIES_IN_SUM; i++) {
224 			memset(buf, 0, BUF_SZ);
225 			if (i % 10 == 0) {
226 				buf[0] = '\n';
227 				ret = write(fd, buf, strlen(buf));
228 				ASSERT(ret >= 0);
229 			}
230 			snprintf(buf, BUF_SZ, "[%3d: %6x]", i,
231 					le32_to_cpu(sum_blk->entries[i].nid));
232 			ret = write(fd, buf, strlen(buf));
233 			ASSERT(ret >= 0);
234 		}
235 		if (ret == SEG_TYPE_NODE || ret == SEG_TYPE_DATA ||
236 					ret == SEG_TYPE_MAX)
237 			free(sum_blk);
238 	}
239 	close(fd);
240 }
241 
dump_data_blk(struct f2fs_sb_info * sbi,__u64 offset,u32 blkaddr)242 static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 blkaddr)
243 {
244 	char buf[F2FS_BLKSIZE];
245 
246 	if (blkaddr == NULL_ADDR)
247 		return;
248 
249 	/* get data */
250 	if (blkaddr == NEW_ADDR || !IS_VALID_BLK_ADDR(sbi, blkaddr)) {
251 		memset(buf, 0, F2FS_BLKSIZE);
252 	} else {
253 		int ret;
254 		ret = dev_read_block(buf, blkaddr);
255 		ASSERT(ret >= 0);
256 	}
257 
258 	/* write blkaddr */
259 	dev_write_dump(buf, offset, F2FS_BLKSIZE);
260 }
261 
dump_node_blk(struct f2fs_sb_info * sbi,int ntype,u32 nid,u64 * ofs)262 static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
263 						u32 nid, u64 *ofs)
264 {
265 	struct node_info ni;
266 	struct f2fs_node *node_blk;
267 	u32 skip = 0;
268 	u32 i, idx;
269 
270 	switch (ntype) {
271 	case TYPE_DIRECT_NODE:
272 		skip = idx = ADDRS_PER_BLOCK;
273 		break;
274 	case TYPE_INDIRECT_NODE:
275 		idx = NIDS_PER_BLOCK;
276 		skip = idx * ADDRS_PER_BLOCK;
277 		break;
278 	case TYPE_DOUBLE_INDIRECT_NODE:
279 		skip = 0;
280 		idx = NIDS_PER_BLOCK;
281 		break;
282 	}
283 
284 	if (nid == 0) {
285 		*ofs += skip;
286 		return;
287 	}
288 
289 	get_node_info(sbi, nid, &ni);
290 
291 	node_blk = calloc(BLOCK_SZ, 1);
292 	dev_read_block(node_blk, ni.blk_addr);
293 
294 	for (i = 0; i < idx; i++, (*ofs)++) {
295 		switch (ntype) {
296 		case TYPE_DIRECT_NODE:
297 			dump_data_blk(sbi, *ofs * F2FS_BLKSIZE,
298 					le32_to_cpu(node_blk->dn.addr[i]));
299 			break;
300 		case TYPE_INDIRECT_NODE:
301 			dump_node_blk(sbi, TYPE_DIRECT_NODE,
302 					le32_to_cpu(node_blk->in.nid[i]), ofs);
303 			break;
304 		case TYPE_DOUBLE_INDIRECT_NODE:
305 			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
306 					le32_to_cpu(node_blk->in.nid[i]), ofs);
307 			break;
308 		}
309 	}
310 	free(node_blk);
311 }
312 
dump_inode_blk(struct f2fs_sb_info * sbi,u32 nid,struct f2fs_node * node_blk)313 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
314 					struct f2fs_node *node_blk)
315 {
316 	u32 i = 0;
317 	u64 ofs = 0;
318 
319 	/* TODO: need to dump xattr */
320 
321 	if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
322 		DBG(3, "ino[0x%x] has inline data!\n", nid);
323 		/* recover from inline data */
324 		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
325 							0, MAX_INLINE_DATA);
326 		return;
327 	}
328 
329 	/* check data blocks in inode */
330 	for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
331 		dump_data_blk(sbi, ofs * F2FS_BLKSIZE,
332 				le32_to_cpu(node_blk->i.i_addr[i]));
333 
334 	/* check node blocks in inode */
335 	for (i = 0; i < 5; i++) {
336 		if (i == 0 || i == 1)
337 			dump_node_blk(sbi, TYPE_DIRECT_NODE,
338 					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
339 		else if (i == 2 || i == 3)
340 			dump_node_blk(sbi, TYPE_INDIRECT_NODE,
341 					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
342 		else if (i == 4)
343 			dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE,
344 					le32_to_cpu(node_blk->i.i_nid[i]), &ofs);
345 		else
346 			ASSERT(0);
347 	}
348 }
349 
dump_file(struct f2fs_sb_info * sbi,struct node_info * ni,struct f2fs_node * node_blk,int force)350 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
351 				struct f2fs_node *node_blk, int force)
352 {
353 	struct f2fs_inode *inode = &node_blk->i;
354 	u32 imode = le32_to_cpu(inode->i_mode);
355 	u32 namelen = le32_to_cpu(inode->i_namelen);
356 	unsigned char name[F2FS_NAME_LEN + 1] = {0};
357 	char path[1024] = {0};
358 	char ans[255] = {0};
359 	int enc_name = file_enc_name(inode);
360 	int ret;
361 
362 	if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) {
363 		MSG(force, "Not a regular file or wrong name info\n\n");
364 		return;
365 	}
366 	if (force)
367 		goto dump;
368 
369 	printf("Do you want to dump this file into ./lost_found/? [Y/N] ");
370 	ret = scanf("%s", ans);
371 	ASSERT(ret >= 0);
372 
373 	if (!strcasecmp(ans, "y")) {
374 dump:
375 		ret = system("mkdir -p ./lost_found");
376 		ASSERT(ret >= 0);
377 
378 		/* make a file */
379 		namelen = convert_encrypted_name(inode->i_name, namelen,
380 							name, enc_name);
381 		name[namelen] = 0;
382 		sprintf(path, "./lost_found/%s", name);
383 
384 		c.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666);
385 		ASSERT(c.dump_fd >= 0);
386 
387 		/* dump file's data */
388 		dump_inode_blk(sbi, ni->ino, node_blk);
389 
390 		/* adjust file size */
391 		ret = ftruncate(c.dump_fd, le32_to_cpu(inode->i_size));
392 		ASSERT(ret >= 0);
393 
394 		close(c.dump_fd);
395 	}
396 }
397 
dump_node(struct f2fs_sb_info * sbi,nid_t nid,int force)398 void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
399 {
400 	struct node_info ni;
401 	struct f2fs_node *node_blk;
402 
403 	get_node_info(sbi, nid, &ni);
404 
405 	node_blk = calloc(BLOCK_SZ, 1);
406 	dev_read_block(node_blk, ni.blk_addr);
407 
408 	DBG(1, "Node ID               [0x%x]\n", nid);
409 	DBG(1, "nat_entry.block_addr  [0x%x]\n", ni.blk_addr);
410 	DBG(1, "nat_entry.version     [0x%x]\n", ni.version);
411 	DBG(1, "nat_entry.ino         [0x%x]\n", ni.ino);
412 
413 	if (ni.blk_addr == 0x0)
414 		MSG(force, "Invalid nat entry\n\n");
415 
416 	DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino));
417 	DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid));
418 
419 	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
420 			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
421 			ni.ino == ni.nid) {
422 		print_node_info(node_blk, force);
423 		dump_file(sbi, &ni, node_blk, force);
424 	} else {
425 		print_node_info(node_blk, force);
426 		MSG(force, "Invalid (i)node block\n\n");
427 	}
428 
429 	free(node_blk);
430 }
431 
dump_node_from_blkaddr(u32 blk_addr)432 static void dump_node_from_blkaddr(u32 blk_addr)
433 {
434 	struct f2fs_node *node_blk;
435 	int ret;
436 
437 	node_blk = calloc(BLOCK_SZ, 1);
438 	ASSERT(node_blk);
439 
440 	ret = dev_read_block(node_blk, blk_addr);
441 	ASSERT(ret >= 0);
442 
443 	if (c.dbg_lv > 0)
444 		print_node_info(node_blk, 0);
445 	else
446 		print_inode_info(&node_blk->i, 1);
447 
448 	free(node_blk);
449 }
450 
dump_data_offset(u32 blk_addr,int ofs_in_node)451 static void dump_data_offset(u32 blk_addr, int ofs_in_node)
452 {
453 	struct f2fs_node *node_blk;
454 	unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
455 	unsigned int bidx = 0;
456 	unsigned int node_ofs;
457 	int ret;
458 
459 	node_blk = calloc(BLOCK_SZ, 1);
460 	ASSERT(node_blk);
461 
462 	ret = dev_read_block(node_blk, blk_addr);
463 	ASSERT(ret >= 0);
464 
465 	node_ofs = ofs_of_node(node_blk);
466 
467 	if (node_ofs == 0)
468 		goto got_it;
469 
470 	if (node_ofs > 0 && node_ofs <= 2) {
471 		bidx = node_ofs - 1;
472 	} else if (node_ofs <= indirect_blks) {
473 		int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
474 		bidx = node_ofs - 2 - dec;
475 	} else {
476 		int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
477 		bidx = node_ofs - 5 - dec;
478 	}
479 	bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(&node_blk->i);
480 got_it:
481 	bidx +=  ofs_in_node;
482 
483 	setlocale(LC_ALL, "");
484 	MSG(0, " - Data offset       : 0x%x (4KB), %'u (bytes)\n",
485 				bidx, bidx * 4096);
486 	free(node_blk);
487 }
488 
dump_node_offset(u32 blk_addr)489 static void dump_node_offset(u32 blk_addr)
490 {
491 	struct f2fs_node *node_blk;
492 	int ret;
493 
494 	node_blk = calloc(BLOCK_SZ, 1);
495 	ASSERT(node_blk);
496 
497 	ret = dev_read_block(node_blk, blk_addr);
498 	ASSERT(ret >= 0);
499 
500 	MSG(0, " - Node offset       : 0x%x\n", ofs_of_node(node_blk));
501 	free(node_blk);
502 }
503 
dump_info_from_blkaddr(struct f2fs_sb_info * sbi,u32 blk_addr)504 int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
505 {
506 	nid_t nid;
507 	int type;
508 	struct f2fs_summary sum_entry;
509 	struct node_info ni, ino_ni;
510 	int ret = 0;
511 
512 	MSG(0, "\n== Dump data from block address ==\n\n");
513 
514 	if (blk_addr < SM_I(sbi)->seg0_blkaddr) {
515 		MSG(0, "\nFS Reserved Area for SEG #0: ");
516 		ret = -EINVAL;
517 	} else if (blk_addr < SIT_I(sbi)->sit_base_addr) {
518 		MSG(0, "\nFS Metadata Area: ");
519 		ret = -EINVAL;
520 	} else if (blk_addr < NM_I(sbi)->nat_blkaddr) {
521 		MSG(0, "\nFS SIT Area: ");
522 		ret = -EINVAL;
523 	} else if (blk_addr < SM_I(sbi)->ssa_blkaddr) {
524 		MSG(0, "\nFS NAT Area: ");
525 		ret = -EINVAL;
526 	} else if (blk_addr < SM_I(sbi)->main_blkaddr) {
527 		MSG(0, "\nFS SSA Area: ");
528 		ret = -EINVAL;
529 	} else if (blk_addr > __end_block_addr(sbi)) {
530 		MSG(0, "\nOut of address space: ");
531 		ret = -EINVAL;
532 	}
533 
534 	if (ret) {
535 		MSG(0, "User data is from 0x%x to 0x%x\n\n",
536 			SM_I(sbi)->main_blkaddr,
537 			__end_block_addr(sbi));
538 		return ret;
539 	}
540 
541 	type = get_sum_entry(sbi, blk_addr, &sum_entry);
542 	nid = le32_to_cpu(sum_entry.nid);
543 
544 	get_node_info(sbi, nid, &ni);
545 
546 	DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n");
547 	DBG(1, "Block_addr            [0x%x]\n", blk_addr);
548 	DBG(1, " - Segno              [0x%x]\n", GET_SEGNO(sbi, blk_addr));
549 	DBG(1, " - Offset             [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr));
550 	DBG(1, "SUM.nid               [0x%x]\n", nid);
551 	DBG(1, "SUM.type              [%s]\n", type >= 0 ?
552 						seg_type_name[type] :
553 						"Broken");
554 	DBG(1, "SUM.version           [%d]\n", sum_entry.version);
555 	DBG(1, "SUM.ofs_in_node       [0x%x]\n", sum_entry.ofs_in_node);
556 	DBG(1, "NAT.blkaddr           [0x%x]\n", ni.blk_addr);
557 	DBG(1, "NAT.ino               [0x%x]\n", ni.ino);
558 
559 	get_node_info(sbi, ni.ino, &ino_ni);
560 
561 	/* inode block address */
562 	if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) {
563 		MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n",
564 			blk_addr);
565 		return -EINVAL;
566 	}
567 
568 	/* print inode */
569 	if (c.dbg_lv > 0)
570 		dump_node_from_blkaddr(ino_ni.blk_addr);
571 
572 	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
573 		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
574 		MSG(0, " - Direct node block : id = 0x%x from 0x%x\n",
575 					nid, ni.blk_addr);
576 		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
577 					ni.ino, ino_ni.blk_addr);
578 		dump_node_from_blkaddr(ino_ni.blk_addr);
579 		dump_data_offset(ni.blk_addr,
580 			le16_to_cpu(sum_entry.ofs_in_node));
581 	} else {
582 		MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr);
583 		if (ni.ino == ni.nid) {
584 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
585 					ni.ino, ino_ni.blk_addr);
586 			dump_node_from_blkaddr(ino_ni.blk_addr);
587 		} else {
588 			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
589 					nid, ni.blk_addr);
590 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
591 					ni.ino, ino_ni.blk_addr);
592 			dump_node_from_blkaddr(ino_ni.blk_addr);
593 			dump_node_offset(ni.blk_addr);
594 		}
595 	}
596 
597 	return 0;
598 }
599