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 = 0; 257 258 get_node_info(sbi, nid, &ni); 259 260 node_blk = calloc(BLOCK_SZ, 1); 261 ASSERT(node_blk); 262 263 dev_read_block(node_blk, ni.blk_addr); 264 265 switch (ntype) { 266 case TYPE_DIRECT_NODE: 267 skip = idx = ADDRS_PER_BLOCK(&node_blk->i); 268 break; 269 case TYPE_INDIRECT_NODE: 270 idx = NIDS_PER_BLOCK; 271 skip = idx * ADDRS_PER_BLOCK(&node_blk->i); 272 break; 273 case TYPE_DOUBLE_INDIRECT_NODE: 274 skip = 0; 275 idx = NIDS_PER_BLOCK; 276 break; 277 } 278 279 if (nid == 0) { 280 *ofs += skip; 281 return; 282 } 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 if (!xattr) 313 return; 314 315 list_for_each_xattr(ent, xattr) { 316 char *name = strndup(ent->e_name, ent->e_name_len); 317 void *value = ent->e_name + ent->e_name_len; 318 319 if (!name) 320 continue; 321 322 switch (ent->e_name_index) { 323 case F2FS_XATTR_INDEX_USER: 324 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 325 XATTR_USER_PREFIX, name); 326 break; 327 328 case F2FS_XATTR_INDEX_SECURITY: 329 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 330 XATTR_SECURITY_PREFIX, name); 331 break; 332 case F2FS_XATTR_INDEX_TRUSTED: 333 ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s", 334 XATTR_TRUSTED_PREFIX, name); 335 break; 336 default: 337 MSG(0, "Unknown xattr index 0x%x\n", ent->e_name_index); 338 free(name); 339 continue; 340 } 341 if (ret >= F2FS_NAME_LEN) { 342 MSG(0, "XATTR index 0x%x name too long\n", ent->e_name_index); 343 free(name); 344 continue; 345 } 346 347 DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name); 348 #if defined(__linux__) 349 ret = fsetxattr(c.dump_fd, xattr_name, value, 350 le16_to_cpu(ent->e_value_size), 0); 351 #elif defined(__APPLE__) 352 ret = fsetxattr(c.dump_fd, xattr_name, value, 353 le16_to_cpu(ent->e_value_size), 0, 354 XATTR_CREATE); 355 #endif 356 if (ret) 357 MSG(0, "XATTR index 0x%x set xattr failed error %d\n", 358 ent->e_name_index, errno); 359 360 free(name); 361 } 362 363 free(xattr); 364 } 365 #else 366 static void dump_xattr(struct f2fs_sb_info *UNUSED(sbi), 367 struct f2fs_node *UNUSED(node_blk)) 368 { 369 MSG(0, "XATTR does not support\n"); 370 } 371 #endif 372 373 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid, 374 struct f2fs_node *node_blk) 375 { 376 u32 i = 0; 377 u64 ofs = 0; 378 379 if((node_blk->i.i_inline & F2FS_INLINE_DATA)) { 380 DBG(3, "ino[0x%x] has inline data!\n", nid); 381 /* recover from inline data */ 382 dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET, 383 0, MAX_INLINE_DATA(node_blk)); 384 return; 385 } 386 387 /* check data blocks in inode */ 388 for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++) 389 dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu( 390 node_blk->i.i_addr[get_extra_isize(node_blk) + i])); 391 392 /* check node blocks in inode */ 393 for (i = 0; i < 5; i++) { 394 if (i == 0 || i == 1) 395 dump_node_blk(sbi, TYPE_DIRECT_NODE, 396 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 397 else if (i == 2 || i == 3) 398 dump_node_blk(sbi, TYPE_INDIRECT_NODE, 399 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 400 else if (i == 4) 401 dump_node_blk(sbi, TYPE_DOUBLE_INDIRECT_NODE, 402 le32_to_cpu(node_blk->i.i_nid[i]), &ofs); 403 else 404 ASSERT(0); 405 } 406 407 dump_xattr(sbi, node_blk); 408 } 409 410 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni, 411 struct f2fs_node *node_blk, int force) 412 { 413 struct f2fs_inode *inode = &node_blk->i; 414 u32 imode = le16_to_cpu(inode->i_mode); 415 u32 namelen = le32_to_cpu(inode->i_namelen); 416 char name[F2FS_NAME_LEN + 1] = {0}; 417 char path[1024] = {0}; 418 char ans[255] = {0}; 419 int is_encrypted = file_is_encrypt(inode); 420 int ret; 421 422 if (is_encrypted) { 423 MSG(force, "File is encrypted\n"); 424 return; 425 } 426 427 if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) { 428 MSG(force, "Not a regular file or wrong name info\n\n"); 429 return; 430 } 431 if (force) 432 goto dump; 433 434 printf("Do you want to dump this file into ./lost_found/? [Y/N] "); 435 ret = scanf("%s", ans); 436 ASSERT(ret >= 0); 437 438 if (!strcasecmp(ans, "y")) { 439 dump: 440 ret = system("mkdir -p ./lost_found"); 441 ASSERT(ret >= 0); 442 443 /* make a file */ 444 strncpy(name, (const char *)inode->i_name, namelen); 445 name[namelen] = 0; 446 sprintf(path, "./lost_found/%s", name); 447 448 c.dump_fd = open(path, O_TRUNC|O_CREAT|O_RDWR, 0666); 449 ASSERT(c.dump_fd >= 0); 450 451 /* dump file's data */ 452 dump_inode_blk(sbi, ni->ino, node_blk); 453 454 /* adjust file size */ 455 ret = ftruncate(c.dump_fd, le32_to_cpu(inode->i_size)); 456 ASSERT(ret >= 0); 457 458 close(c.dump_fd); 459 } 460 } 461 462 static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr) 463 { 464 struct seg_entry *se; 465 u32 offset; 466 467 se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr)); 468 offset = OFFSET_IN_SEG(sbi, blk_addr); 469 470 return f2fs_test_bit(offset, 471 (const char *)se->cur_valid_map) != 0; 472 } 473 474 void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force) 475 { 476 struct node_info ni; 477 struct f2fs_node *node_blk; 478 479 get_node_info(sbi, nid, &ni); 480 481 node_blk = calloc(BLOCK_SZ, 1); 482 ASSERT(node_blk); 483 484 dev_read_block(node_blk, ni.blk_addr); 485 486 DBG(1, "Node ID [0x%x]\n", nid); 487 DBG(1, "nat_entry.block_addr [0x%x]\n", ni.blk_addr); 488 DBG(1, "nat_entry.version [0x%x]\n", ni.version); 489 DBG(1, "nat_entry.ino [0x%x]\n", ni.ino); 490 491 if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) { 492 MSG(force, "Invalid node blkaddr: %u\n\n", ni.blk_addr); 493 goto out; 494 } 495 496 if (ni.blk_addr == 0x0) 497 MSG(force, "Invalid nat entry\n\n"); 498 else if (!is_sit_bitmap_set(sbi, ni.blk_addr)) 499 MSG(force, "Invalid sit bitmap, %u\n\n", ni.blk_addr); 500 501 DBG(1, "node_blk.footer.ino [0x%x]\n", le32_to_cpu(node_blk->footer.ino)); 502 DBG(1, "node_blk.footer.nid [0x%x]\n", le32_to_cpu(node_blk->footer.nid)); 503 504 if (le32_to_cpu(node_blk->footer.ino) == ni.ino && 505 le32_to_cpu(node_blk->footer.nid) == ni.nid) { 506 print_node_info(sbi, node_blk, force); 507 508 if (ni.ino == ni.nid) 509 dump_file(sbi, &ni, node_blk, force); 510 } else { 511 print_node_info(sbi, node_blk, force); 512 MSG(force, "Invalid (i)node block\n\n"); 513 } 514 out: 515 free(node_blk); 516 } 517 518 static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) 519 { 520 struct f2fs_node *node_blk; 521 int ret; 522 523 node_blk = calloc(BLOCK_SZ, 1); 524 ASSERT(node_blk); 525 526 ret = dev_read_block(node_blk, blk_addr); 527 ASSERT(ret >= 0); 528 529 if (c.dbg_lv > 0) 530 print_node_info(sbi, node_blk, 0); 531 else 532 print_inode_info(sbi, node_blk, 1); 533 534 free(node_blk); 535 } 536 537 unsigned int start_bidx_of_node(unsigned int node_ofs, 538 struct f2fs_node *node_blk) 539 { 540 unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; 541 unsigned int bidx; 542 543 if (node_ofs == 0) 544 return 0; 545 546 if (node_ofs <= 2) { 547 bidx = node_ofs - 1; 548 } else if (node_ofs <= indirect_blks) { 549 int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1); 550 bidx = node_ofs - 2 - dec; 551 } else { 552 int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); 553 bidx = node_ofs - 5 - dec; 554 } 555 return bidx * ADDRS_PER_BLOCK(&node_blk->i) + 556 ADDRS_PER_INODE(&node_blk->i); 557 } 558 559 static void dump_data_offset(u32 blk_addr, int ofs_in_node) 560 { 561 struct f2fs_node *node_blk; 562 unsigned int bidx; 563 unsigned int node_ofs; 564 int ret; 565 566 node_blk = calloc(BLOCK_SZ, 1); 567 ASSERT(node_blk); 568 569 ret = dev_read_block(node_blk, blk_addr); 570 ASSERT(ret >= 0); 571 572 node_ofs = ofs_of_node(node_blk); 573 574 bidx = start_bidx_of_node(node_ofs, node_blk); 575 bidx += ofs_in_node; 576 577 setlocale(LC_ALL, ""); 578 MSG(0, " - Data offset : 0x%x (4KB), %'u (bytes)\n", 579 bidx, bidx * 4096); 580 free(node_blk); 581 } 582 583 static void dump_node_offset(u32 blk_addr) 584 { 585 struct f2fs_node *node_blk; 586 int ret; 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 MSG(0, " - Node offset : 0x%x\n", ofs_of_node(node_blk)); 595 free(node_blk); 596 } 597 598 static int has_dirent(u32 blk_addr, int is_inline, int *enc_name) 599 { 600 struct f2fs_node *node_blk; 601 int ret, is_dentry = 0; 602 603 node_blk = calloc(BLOCK_SZ, 1); 604 ASSERT(node_blk); 605 606 ret = dev_read_block(node_blk, blk_addr); 607 ASSERT(ret >= 0); 608 609 if (IS_INODE(node_blk) && S_ISDIR(le16_to_cpu(node_blk->i.i_mode))) 610 is_dentry = 1; 611 612 if (is_inline && !(node_blk->i.i_inline & F2FS_INLINE_DENTRY)) 613 is_dentry = 0; 614 615 *enc_name = file_is_encrypt(&node_blk->i); 616 617 free(node_blk); 618 619 return is_dentry; 620 } 621 622 static void dump_dirent(u32 blk_addr, int is_inline, int enc_name) 623 { 624 struct f2fs_dentry_ptr d; 625 void *inline_dentry, *blk; 626 int ret, i = 0; 627 628 blk = calloc(BLOCK_SZ, 1); 629 ASSERT(blk); 630 631 ret = dev_read_block(blk, blk_addr); 632 ASSERT(ret >= 0); 633 634 if (is_inline) { 635 inline_dentry = inline_data_addr((struct f2fs_node *)blk); 636 make_dentry_ptr(&d, blk, inline_dentry, 2); 637 } else { 638 make_dentry_ptr(&d, NULL, blk, 1); 639 } 640 641 DBG(1, "%sDentry block:\n", is_inline ? "Inline " : ""); 642 643 while (i < d.max) { 644 struct f2fs_dir_entry *de; 645 char en[F2FS_PRINT_NAMELEN]; 646 u16 name_len; 647 int enc; 648 649 if (!test_bit_le(i, d.bitmap)) { 650 i++; 651 continue; 652 } 653 654 de = &d.dentry[i]; 655 656 if (!de->name_len) { 657 i++; 658 continue; 659 } 660 661 name_len = le16_to_cpu(de->name_len); 662 enc = enc_name; 663 664 if (de->file_type == F2FS_FT_DIR) { 665 if ((d.filename[i][0] == '.' && name_len == 1) || 666 (d.filename[i][0] == '.' && 667 d.filename[i][1] == '.' && name_len == 2)) { 668 enc = 0; 669 } 670 } 671 672 pretty_print_filename(d.filename[i], name_len, en, enc); 673 674 DBG(1, "bitmap pos[0x%x] name[%s] len[0x%x] hash[0x%x] ino[0x%x] type[0x%x]\n", 675 i, en, 676 name_len, 677 le32_to_cpu(de->hash_code), 678 le32_to_cpu(de->ino), 679 de->file_type); 680 681 i += GET_DENTRY_SLOTS(name_len); 682 } 683 684 free(blk); 685 } 686 687 int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr) 688 { 689 nid_t nid; 690 int type; 691 struct f2fs_summary sum_entry; 692 struct node_info ni, ino_ni; 693 int enc_name; 694 int ret = 0; 695 696 MSG(0, "\n== Dump data from block address ==\n\n"); 697 698 if (blk_addr < SM_I(sbi)->seg0_blkaddr) { 699 MSG(0, "\nFS Reserved Area for SEG #0: "); 700 ret = -EINVAL; 701 } else if (blk_addr < SIT_I(sbi)->sit_base_addr) { 702 MSG(0, "\nFS Metadata Area: "); 703 ret = -EINVAL; 704 } else if (blk_addr < NM_I(sbi)->nat_blkaddr) { 705 MSG(0, "\nFS SIT Area: "); 706 ret = -EINVAL; 707 } else if (blk_addr < SM_I(sbi)->ssa_blkaddr) { 708 MSG(0, "\nFS NAT Area: "); 709 ret = -EINVAL; 710 } else if (blk_addr < SM_I(sbi)->main_blkaddr) { 711 MSG(0, "\nFS SSA Area: "); 712 ret = -EINVAL; 713 } else if (blk_addr > __end_block_addr(sbi)) { 714 MSG(0, "\nOut of address space: "); 715 ret = -EINVAL; 716 } 717 718 if (ret) { 719 MSG(0, "User data is from 0x%x to 0x%x\n\n", 720 SM_I(sbi)->main_blkaddr, 721 __end_block_addr(sbi)); 722 return ret; 723 } 724 725 if (!is_sit_bitmap_set(sbi, blk_addr)) 726 MSG(0, "\nblkaddr is not valid\n"); 727 728 type = get_sum_entry(sbi, blk_addr, &sum_entry); 729 nid = le32_to_cpu(sum_entry.nid); 730 731 get_node_info(sbi, nid, &ni); 732 733 DBG(1, "Note: blkaddr = main_blkaddr + segno * 512 + offset\n"); 734 DBG(1, "Block_addr [0x%x]\n", blk_addr); 735 DBG(1, " - Segno [0x%x]\n", GET_SEGNO(sbi, blk_addr)); 736 DBG(1, " - Offset [0x%x]\n", OFFSET_IN_SEG(sbi, blk_addr)); 737 DBG(1, "SUM.nid [0x%x]\n", nid); 738 DBG(1, "SUM.type [%s]\n", type >= 0 ? 739 seg_type_name[type] : 740 "Broken"); 741 DBG(1, "SUM.version [%d]\n", sum_entry.version); 742 DBG(1, "SUM.ofs_in_node [0x%x]\n", sum_entry.ofs_in_node); 743 DBG(1, "NAT.blkaddr [0x%x]\n", ni.blk_addr); 744 DBG(1, "NAT.ino [0x%x]\n", ni.ino); 745 746 get_node_info(sbi, ni.ino, &ino_ni); 747 748 /* inode block address */ 749 if (ni.blk_addr == NULL_ADDR || ino_ni.blk_addr == NULL_ADDR) { 750 MSG(0, "FS Userdata Area: Obsolete block from 0x%x\n", 751 blk_addr); 752 return -EINVAL; 753 } 754 755 /* print inode */ 756 if (c.dbg_lv > 0) 757 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 758 759 if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) { 760 MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr); 761 MSG(0, " - Direct node block : id = 0x%x from 0x%x\n", 762 nid, ni.blk_addr); 763 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 764 ni.ino, ino_ni.blk_addr); 765 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 766 dump_data_offset(ni.blk_addr, 767 le16_to_cpu(sum_entry.ofs_in_node)); 768 769 if (has_dirent(ino_ni.blk_addr, 0, &enc_name)) 770 dump_dirent(blk_addr, 0, enc_name); 771 } else { 772 MSG(0, "FS Userdata Area: Node block from 0x%x\n", blk_addr); 773 if (ni.ino == ni.nid) { 774 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 775 ni.ino, ino_ni.blk_addr); 776 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 777 778 if (has_dirent(ino_ni.blk_addr, 1, &enc_name)) 779 dump_dirent(blk_addr, 1, enc_name); 780 } else { 781 MSG(0, " - Node block : id = 0x%x from 0x%x\n", 782 nid, ni.blk_addr); 783 MSG(0, " - Inode block : id = 0x%x from 0x%x\n", 784 ni.ino, ino_ni.blk_addr); 785 dump_node_from_blkaddr(sbi, ino_ni.blk_addr); 786 dump_node_offset(ni.blk_addr); 787 } 788 } 789 790 return 0; 791 } 792