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 "node.h" 14 #include "fsck.h" 15 #include "xattr.h" 16 #ifdef HAVE_ATTR_XATTR_H 17 #include <attr/xattr.h> 18 #endif 19 #ifdef HAVE_LINUX_XATTR_H 20 #include <linux/xattr.h> 21 #endif 22 #include <locale.h> 23 24 #define BUF_SZ 80 25 26 const char *seg_type_name[SEG_TYPE_MAX + 1] = { 27 "SEG_TYPE_DATA", 28 "SEG_TYPE_CUR_DATA", 29 "SEG_TYPE_NODE", 30 "SEG_TYPE_CUR_NODE", 31 "SEG_TYPE_NONE", 32 }; 33 34 void nat_dump(struct f2fs_sb_info *sbi, nid_t start_nat, nid_t end_nat) 35 { 36 struct f2fs_nat_block *nat_block; 37 struct f2fs_node *node_block; 38 nid_t nid; 39 pgoff_t block_addr; 40 char buf[BUF_SZ]; 41 int fd, ret, pack; 42 43 nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 44 ASSERT(nat_block); 45 node_block = (struct f2fs_node *)calloc(BLOCK_SZ, 1); 46 ASSERT(node_block); 47 48 fd = open("dump_nat", O_CREAT|O_WRONLY|O_TRUNC, 0666); 49 ASSERT(fd >= 0); 50 51 for (nid = start_nat; nid < end_nat; nid++) { 52 struct f2fs_nat_entry raw_nat; 53 struct node_info ni; 54 if(nid == 0 || nid == F2FS_NODE_INO(sbi) || 55 nid == F2FS_META_INO(sbi)) 56 continue; 57 58 ni.nid = nid; 59 block_addr = current_nat_addr(sbi, nid, &pack); 60 61 if (lookup_nat_in_journal(sbi, nid, &raw_nat) >= 0) { 62 node_info_from_raw_nat(&ni, &raw_nat); 63 ret = dev_read_block(node_block, ni.blk_addr); 64 ASSERT(ret >= 0); 65 if (ni.blk_addr != 0x0) { 66 memset(buf, 0, BUF_SZ); 67 snprintf(buf, BUF_SZ, 68 "nid:%5u\tino:%5u\toffset:%5u" 69 "\tblkaddr:%10u\tpack:%d\n", 70 ni.nid, ni.ino, 71 le32_to_cpu(node_block->footer.flag) >> 72 OFFSET_BIT_SHIFT, 73 ni.blk_addr, pack); 74 ret = write(fd, buf, strlen(buf)); 75 ASSERT(ret >= 0); 76 } 77 } else { 78 ret = dev_read_block(nat_block, block_addr); 79 ASSERT(ret >= 0); 80 node_info_from_raw_nat(&ni, 81 &nat_block->entries[nid % NAT_ENTRY_PER_BLOCK]); 82 if (ni.blk_addr == 0) 83 continue; 84 85 ret = dev_read_block(node_block, ni.blk_addr); 86 ASSERT(ret >= 0); 87 memset(buf, 0, BUF_SZ); 88 snprintf(buf, BUF_SZ, 89 "nid:%5u\tino:%5u\toffset:%5u" 90 "\tblkaddr:%10u\tpack:%d\n", 91 ni.nid, ni.ino, 92 le32_to_cpu(node_block->footer.flag) >> 93 OFFSET_BIT_SHIFT, 94 ni.blk_addr, pack); 95 ret = write(fd, buf, strlen(buf)); 96 ASSERT(ret >= 0); 97 } 98 } 99 100 free(nat_block); 101 free(node_block); 102 103 close(fd); 104 } 105 106 void sit_dump(struct f2fs_sb_info *sbi, unsigned int start_sit, 107 unsigned int end_sit) 108 { 109 struct seg_entry *se; 110 struct sit_info *sit_i = SIT_I(sbi); 111 unsigned int segno; 112 char buf[BUF_SZ]; 113 u32 free_segs = 0;; 114 u64 valid_blocks = 0; 115 int ret; 116 int fd, i; 117 unsigned int offset; 118 119 fd = open("dump_sit", O_CREAT|O_WRONLY|O_TRUNC, 0666); 120 ASSERT(fd >= 0); 121 122 snprintf(buf, BUF_SZ, "segment_type(0:HD, 1:WD, 2:CD, " 123 "3:HN, 4:WN, 5:CN)\n"); 124 ret = write(fd, buf, strlen(buf)); 125 ASSERT(ret >= 0); 126 127 for (segno = start_sit; segno < end_sit; segno++) { 128 se = get_seg_entry(sbi, segno); 129 offset = SIT_BLOCK_OFFSET(sit_i, segno); 130 memset(buf, 0, BUF_SZ); 131 snprintf(buf, BUF_SZ, 132 "\nsegno:%8u\tvblocks:%3u\tseg_type:%d\tsit_pack:%d\n\n", 133 segno, se->valid_blocks, se->type, 134 f2fs_test_bit(offset, sit_i->sit_bitmap) ? 2 : 1); 135 136 ret = write(fd, buf, strlen(buf)); 137 ASSERT(ret >= 0); 138 139 if (se->valid_blocks == 0x0) { 140 free_segs++; 141 continue; 142 } 143 144 ASSERT(se->valid_blocks <= 512); 145 valid_blocks += se->valid_blocks; 146 147 for (i = 0; i < 64; i++) { 148 memset(buf, 0, BUF_SZ); 149 snprintf(buf, BUF_SZ, " %02x", 150 *(se->cur_valid_map + i)); 151 ret = write(fd, buf, strlen(buf)); 152 ASSERT(ret >= 0); 153 154 if ((i + 1) % 16 == 0) { 155 snprintf(buf, BUF_SZ, "\n"); 156 ret = write(fd, buf, strlen(buf)); 157 ASSERT(ret >= 0); 158 } 159 } 160 } 161 162 memset(buf, 0, BUF_SZ); 163 snprintf(buf, BUF_SZ, 164 "valid_blocks:[0x%" PRIx64 "]\tvalid_segs:%d\t free_segs:%d\n", 165 valid_blocks, 166 SM_I(sbi)->main_segments - free_segs, 167 free_segs); 168 ret = write(fd, buf, strlen(buf)); 169 ASSERT(ret >= 0); 170 171 close(fd); 172 } 173 174 void ssa_dump(struct f2fs_sb_info *sbi, int start_ssa, int end_ssa) 175 { 176 struct f2fs_summary_block *sum_blk; 177 char buf[BUF_SZ]; 178 int segno, type, i, ret; 179 int fd; 180 181 fd = open("dump_ssa", O_CREAT|O_WRONLY|O_TRUNC, 0666); 182 ASSERT(fd >= 0); 183 184 snprintf(buf, BUF_SZ, "Note: dump.f2fs -b blkaddr = 0x%x + segno * " 185 " 0x200 + offset\n", 186 sbi->sm_info->main_blkaddr); 187 ret = write(fd, buf, strlen(buf)); 188 ASSERT(ret >= 0); 189 190 for (segno = start_ssa; segno < end_ssa; segno++) { 191 sum_blk = get_sum_block(sbi, segno, &type); 192 193 memset(buf, 0, BUF_SZ); 194 switch (type) { 195 case SEG_TYPE_CUR_NODE: 196 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Node\n", segno); 197 break; 198 case SEG_TYPE_CUR_DATA: 199 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Current Data\n", segno); 200 break; 201 case SEG_TYPE_NODE: 202 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Node\n", segno); 203 break; 204 case SEG_TYPE_DATA: 205 snprintf(buf, BUF_SZ, "\n\nsegno: %x, Data\n", segno); 206 break; 207 } 208 ret = write(fd, buf, strlen(buf)); 209 ASSERT(ret >= 0); 210 211 for (i = 0; i < ENTRIES_IN_SUM; i++) { 212 memset(buf, 0, BUF_SZ); 213 if (i % 10 == 0) { 214 buf[0] = '\n'; 215 ret = write(fd, buf, strlen(buf)); 216 ASSERT(ret >= 0); 217 } 218 snprintf(buf, BUF_SZ, "[%3d: %6x]", i, 219 le32_to_cpu(sum_blk->entries[i].nid)); 220 ret = write(fd, buf, strlen(buf)); 221 ASSERT(ret >= 0); 222 } 223 if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA || 224 type == SEG_TYPE_MAX) 225 free(sum_blk); 226 } 227 close(fd); 228 } 229 230 static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 blkaddr) 231 { 232 char buf[F2FS_BLKSIZE]; 233 234 if (blkaddr == NULL_ADDR) 235 return; 236 237 /* get data */ 238 if (blkaddr == NEW_ADDR || !IS_VALID_BLK_ADDR(sbi, blkaddr)) { 239 memset(buf, 0, F2FS_BLKSIZE); 240 } else { 241 int ret; 242 ret = dev_read_block(buf, blkaddr); 243 ASSERT(ret >= 0); 244 } 245 246 /* write blkaddr */ 247 dev_write_dump(buf, offset, F2FS_BLKSIZE); 248 } 249 250 static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype, 251 u32 nid, u64 *ofs) 252 { 253 struct node_info ni; 254 struct f2fs_node *node_blk; 255 u32 skip = 0; 256 u32 i, idx; 257 258 switch (ntype) { 259 case TYPE_DIRECT_NODE: 260 skip = idx = ADDRS_PER_BLOCK; 261 break; 262 case TYPE_INDIRECT_NODE: 263 idx = NIDS_PER_BLOCK; 264 skip = idx * ADDRS_PER_BLOCK; 265 break; 266 case TYPE_DOUBLE_INDIRECT_NODE: 267 skip = 0; 268 idx = NIDS_PER_BLOCK; 269 break; 270 } 271 272 if (nid == 0) { 273 *ofs += skip; 274 return; 275 } 276 277 get_node_info(sbi, nid, &ni); 278 279 node_blk = calloc(BLOCK_SZ, 1); 280 ASSERT(node_blk); 281 282 dev_read_block(node_blk, ni.blk_addr); 283 284 for (i = 0; i < idx; i++, (*ofs)++) { 285 switch (ntype) { 286 case TYPE_DIRECT_NODE: 287 dump_data_blk(sbi, *ofs * F2FS_BLKSIZE, 288 le32_to_cpu(node_blk->dn.addr[i])); 289 break; 290 case TYPE_INDIRECT_NODE: 291 dump_node_blk(sbi, TYPE_DIRECT_NODE, 292 le32_to_cpu(node_blk->in.nid[i]), ofs); 293 break; 294 case TYPE_DOUBLE_INDIRECT_NODE: 295 dump_node_blk(sbi, TYPE_INDIRECT_NODE, 296 le32_to_cpu(node_blk->in.nid[i]), ofs); 297 break; 298 } 299 } 300 free(node_blk); 301 } 302 303 #ifdef HAVE_FSETXATTR 304 static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk) 305 { 306 void *xattr; 307 struct f2fs_xattr_entry *ent; 308 char xattr_name[F2FS_NAME_LEN] = {0}; 309 int ret; 310 311 xattr = read_all_xattrs(sbi, node_blk); 312 313 list_for_each_xattr(ent, xattr) { 314 char *name = strndup(ent->e_name, ent->e_name_len); 315 void *value = ent->e_name + ent->e_name_len; 316 317 if (!name) 318 continue; 319 320 switch (ent->e_name_index) { 321 case F2FS_XATTR_INDEX_USER: 322 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 323 XATTR_USER_PREFIX, name); 324 break; 325 326 case F2FS_XATTR_INDEX_SECURITY: 327 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 328 XATTR_SECURITY_PREFIX, name); 329 break; 330 case F2FS_XATTR_INDEX_TRUSTED: 331 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 332 XATTR_TRUSTED_PREFIX, name); 333 break; 334 default: 335 MSG(0, "Unknown xattr index 0x%x\n", ent->e_name_index); 336 free(name); 337 continue; 338 } 339 if (ret >= F2FS_NAME_LEN) { 340 MSG(0, "XATTR index 0x%x name too long\n", ent->e_name_index); 341 free(name); 342 continue; 343 } 344 345 DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name); 346 #if defined(__linux__) 347 ret = fsetxattr(c.dump_fd, xattr_name, value, 348 le16_to_cpu(ent->e_value_size), 0); 349 #elif defined(__APPLE__) 350 ret = fsetxattr(c.dump_fd, xattr_name, value, 351 le16_to_cpu(ent->e_value_size), 0, 352 XATTR_CREATE); 353 #endif 354 if (ret) 355 MSG(0, "XATTR index 0x%x set xattr failed error %d\n", 356 ent->e_name_index, errno); 357 358 free(name); 359 } 360 361 free(xattr); 362 } 363 #else 364 static void dump_xattr(struct f2fs_sb_info *UNUSED(sbi), 365 struct f2fs_node *UNUSED(node_blk)) 366 { 367 MSG(0, "XATTR does not support\n"); 368 } 369 #endif 370 371 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid, 372 struct f2fs_node *node_blk) 373 { 374 u32 i = 0; 375 u64 ofs = 0; 376 377 if((node_blk->i.i_inline & F2FS_INLINE_DATA)) { 378 DBG(3, "ino[0x%x] has inline data!\n", nid); 379 /* recover from inline data */ 380 dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET, 381 0, MAX_INLINE_DATA(node_blk)); 382 return; 383 } 384 385 /* check data blocks in inode */ 386 for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++) 387 dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu( 388 node_blk->i.i_addr[get_extra_isize(node_blk) + i])); 389 390 /* check node blocks in inode */ 391 for (i = 0; i < 5; i++) { 392 if (i == 0 || i == 1) 393 dump_node_blk(sbi, TYPE_DIRECT_NODE, 394 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 395 else if (i == 2 || i == 3) 396 dump_node_blk(sbi, TYPE_INDIRECT_NODE, 397 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 398 else if (i == 4) 399 dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE, 400 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 401 else 402 ASSERT(0); 403 } 404 405 dump_xattr(sbi, node_blk); 406 } 407 408 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni, 409 struct f2fs_node *node_blk, int force) 410 { 411 struct f2fs_inode *inode = &node_blk->i; 412 u32 imode = le16_to_cpu(inode->i_mode); 413 u32 namelen = le32_to_cpu(inode->i_namelen); 414 char name[F2FS_NAME_LEN + 1] = {0}; 415 char path[1024] = {0}; 416 char ans[255] = {0}; 417 int is_encrypted = file_is_encrypt(inode); 418 int ret; 419 420 if (is_encrypted) { 421 MSG(force, "File is encrypted\n"); 422 return; 423 } 424 425 if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) { 426 MSG(force, "Not a regular file or wrong name info\n\n"); 427 return; 428 } 429 if (force) 430 goto dump; 431 432 printf("Do you want to dump this file into ./lost_found/? [Y/N] "); 433 ret = scanf("%s", ans); 434 ASSERT(ret >= 0); 435 436 if (!strcasecmp(ans, "y")) { 437 dump: 438 ret = system("mkdir -p ./lost_found"); 439 ASSERT(ret >= 0); 440 441 /* make a file */ 442 strncpy(name, (const char *)inode->i_name, namelen); 443 name[namelen] = 0; 444 sprintf(path, "./lost_found/%s", name); 445 446 c.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666); 447 ASSERT(c.dump_fd >= 0); 448 449 /* dump file's data */ 450 dump_inode_blk(sbi, ni->ino, node_blk); 451 452 /* adjust file size */ 453 ret = ftruncate(c.dump_fd, le32_to_cpu(inode->i_size)); 454 ASSERT(ret >= 0); 455 456 close(c.dump_fd); 457 } 458 } 459 460 static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr) 461 { 462 struct seg_entry *se; 463 u32 offset; 464 465 se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr)); 466 offset = OFFSET_IN_SEG(sbi, blk_addr); 467 468 return f2fs_test_bit(offset, 469 (const char *)se->cur_valid_map) != 0; 470 } 471 472 void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force) 473 { 474 struct node_info ni; 475 struct f2fs_node *node_blk; 476 477 get_node_info(sbi, nid, &ni); 478 479 node_blk = calloc(BLOCK_SZ, 1); 480 ASSERT(node_blk); 481 482 dev_read_block(node_blk, ni.blk_addr); 483 484 DBG(1, "Node ID [0x%x]\n", nid); 485 DBG(1, "nat_entry.block_addr [0x%x]\n", ni.blk_addr); 486 DBG(1, "nat_entry.version [0x%x]\n", ni.version); 487 DBG(1, "nat_entry.ino [0x%x]\n", ni.ino); 488 489 if (ni.blk_addr == 0x0) 490 MSG(force, "Invalid nat entry\n\n"); 491 else if (!is_sit_bitmap_set(sbi, ni.blk_addr)) 492 MSG(force, "Invalid node blk addr\n\n"); 493 494 DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino)); 495 DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid)); 496 497 if (le32_to_cpu(node_blk->footer.ino) == ni.ino && 498 le32_to_cpu(node_blk->footer.nid) == ni.nid) { 499 print_node_info(sbi, node_blk, force); 500 501 if (ni.ino == ni.nid) 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 static int has_dirent(u32 blk_addr, int is_inline, int *enc_name) 584 { 585 struct f2fs_node *node_blk; 586 int ret, is_dentry = 0; 587 588 node_blk = calloc(BLOCK_SZ, 1); 589 ASSERT(node_blk); 590 591 ret = dev_read_block(node_blk, blk_addr); 592 ASSERT(ret >= 0); 593 594 if (IS_INODE(node_blk) && S_ISDIR(le16_to_cpu(node_blk->i.i_mode))) 595 is_dentry = 1; 596 597 if (is_inline && !(node_blk->i.i_inline & F2FS_INLINE_DENTRY)) 598 is_dentry = 0; 599 600 *enc_name = file_is_encrypt(&node_blk->i); 601 602 free(node_blk); 603 604 return is_dentry; 605 } 606 607 static void dump_dirent(u32 blk_addr, int is_inline, int enc_name) 608 { 609 struct f2fs_dentry_ptr d; 610 void *inline_dentry, *blk; 611 int ret, i = 0; 612 613 blk = calloc(BLOCK_SZ, 1); 614 ASSERT(blk); 615 616 ret = dev_read_block(blk, blk_addr); 617 ASSERT(ret >= 0); 618 619 if (is_inline) { 620 inline_dentry = inline_data_addr((struct f2fs_node *)blk); 621 make_dentry_ptr(&d, blk, inline_dentry, 2); 622 } else { 623 make_dentry_ptr(&d, NULL, blk, 1); 624 } 625 626 DBG(1, "%sDentry block:\n", is_inline ? "Inline " : ""); 627 628 while (i < d.max) { 629 struct f2fs_dir_entry *de; 630 unsigned char en[F2FS_NAME_LEN + 1]; 631 u16 en_len, name_len; 632 int enc; 633 634 if (!test_bit_le(i, d.bitmap)) { 635 i++; 636 continue; 637 } 638 639 de = &d.dentry[i]; 640 641 if (!de->name_len) { 642 i++; 643 continue; 644 } 645 646 name_len = le16_to_cpu(de->name_len); 647 enc = enc_name; 648 649 if (de->file_type == F2FS_FT_DIR) { 650 if ((d.filename[i][0] == '.' && name_len == 1) || 651 (d.filename[i][0] == '.' && 652 d.filename[i][1] == '.' && name_len == 2)) { 653 enc = 0; 654 } 655 } 656 657 en_len = convert_encrypted_name(d.filename[i], 658 le16_to_cpu(de->name_len), en, enc); 659 en[en_len] = '\0'; 660 661 DBG(1, "bitmap pos[0x%x] name[%s] len[0x%x] hash[0x%x] ino[0x%x] type[0x%x]\n", 662 i, en, 663 le16_to_cpu(de->name_len), 664 le32_to_cpu(de->hash_code), 665 le32_to_cpu(de->ino), 666 de->file_type); 667 668 i += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); 669 } 670 671 free(blk); 672 } 673 674 int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) 675 { 676 nid_t nid; 677 int type; 678 struct f2fs_summary sum_entry; 679 struct node_info ni, ino_ni; 680 int enc_name; 681 int ret = 0; 682 683 MSG(0, "\n== Dump data from block address ==\n\n"); 684 685 if (blk_addr < SM_I(sbi)->seg0_blkaddr) { 686 MSG(0, "\nFS Reserved Area for SEG #0: "); 687 ret = -EINVAL; 688 } else if (blk_addr < SIT_I(sbi)->sit_base_addr) { 689 MSG(0, "\nFS Metadata Area: "); 690 ret = -EINVAL; 691 } else if (blk_addr < NM_I(sbi)->nat_blkaddr) { 692 MSG(0, "\nFS SIT Area: "); 693 ret = -EINVAL; 694 } else if (blk_addr < SM_I(sbi)->ssa_blkaddr) { 695 MSG(0, "\nFS NAT Area: "); 696 ret = -EINVAL; 697 } else if (blk_addr < SM_I(sbi)->main_blkaddr) { 698 MSG(0, "\nFS SSA Area: "); 699 ret = -EINVAL; 700 } else if (blk_addr > __end_block_addr(sbi)) { 701 MSG(0, "\nOut of address space: "); 702 ret = -EINVAL; 703 } 704 705 if (ret) { 706 MSG(0, "User data is from 0x%x to 0x%x\n\n", 707 SM_I(sbi)->main_blkaddr, 708 __end_block_addr(sbi)); 709 return ret; 710 } 711 712 if (!is_sit_bitmap_set(sbi, blk_addr)) 713 MSG(0, "\nblkaddr is not valid\n"); 714 715 type = get_sum_entry(sbi, blk_addr, &sum_entry); 716 nid = le32_to_cpu(sum_entry.nid); 717 718 get_node_info(sbi, nid, &ni); 719 720 DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n"); 721 DBG(1, "Block_addr [0x%x]\n", blk_addr); 722 DBG(1, " - Segno [0x%x]\n", GET_SEGNO(sbi, blk_addr)); 723 DBG(1, " - Offset [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr)); 724 DBG(1, "SUM.nid [0x%x]\n", nid); 725 DBG(1, "SUM.type [%s]\n", type >= 0 ? 726 seg_type_name[type] : 727 "Broken"); 728 DBG(1, "SUM.version [%d]\n", sum_entry.version); 729 DBG(1, "SUM.ofs_in_node [0x%x]\n", sum_entry.ofs_in_node); 730 DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr); 731 DBG(1, "NAT.ino [0x%x]\n", ni.ino); 732 733 get_node_info(sbi, ni.ino, &ino_ni); 734 735 /* inode block address */ 736 if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) { 737 MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n", 738 blk_addr); 739 return -EINVAL; 740 } 741 742 /* print inode */ 743 if (c.dbg_lv > 0) 744 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 745 746 if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) { 747 MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr); 748 MSG(0, " - Direct node block : id = 0x%x from 0x%x\n", 749 nid, ni.blk_addr); 750 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 751 ni.ino, ino_ni.blk_addr); 752 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 753 dump_data_offset(ni.blk_addr, 754 le16_to_cpu(sum_entry.ofs_in_node)); 755 756 if (has_dirent(ino_ni.blk_addr, 0, &enc_name)) 757 dump_dirent(blk_addr, 0, enc_name); 758 } else { 759 MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr); 760 if (ni.ino == ni.nid) { 761 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 762 ni.ino, ino_ni.blk_addr); 763 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 764 765 if (has_dirent(ino_ni.blk_addr, 1, &enc_name)) 766 dump_dirent(blk_addr, 1, enc_name); 767 } else { 768 MSG(0, " - Node block : id = 0x%x from 0x%x\n", 769 nid, ni.blk_addr); 770 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 771 ni.ino, ino_ni.blk_addr); 772 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 773 dump_node_offset(ni.blk_addr); 774 } 775 } 776 777 return 0; 778 } 779