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