fsck.c revision 8e678b2edfba95f3edbb1730c69da365d659e95d
1/** 2 * fsck.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 "fsck.h" 12 13#define S_SHIFT 12 14static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { 15 [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, 16 [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, 17 [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, 18 [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV, 19 [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, 20 [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK, 21 [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK, 22}; 23 24char *tree_mark; 25int tree_mark_size = 256; 26 27static int add_into_hard_link_list(struct f2fs_sb_info *sbi, u32 nid, u32 link_cnt) 28{ 29 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 30 struct hard_link_node *node = NULL, *tmp = NULL, *prev = NULL; 31 32 node = calloc(sizeof(struct hard_link_node), 1); 33 ASSERT(node != NULL); 34 35 node->nid = nid; 36 node->links = link_cnt; 37 node->next = NULL; 38 39 if (fsck->hard_link_list_head == NULL) { 40 fsck->hard_link_list_head = node; 41 goto out; 42 } 43 44 tmp = fsck->hard_link_list_head; 45 46 /* Find insertion position */ 47 while (tmp && (nid < tmp->nid)) { 48 ASSERT(tmp->nid != nid); 49 prev = tmp; 50 tmp = tmp->next; 51 } 52 53 if (tmp == fsck->hard_link_list_head) { 54 node->next = tmp; 55 fsck->hard_link_list_head = node; 56 } else { 57 prev->next = node; 58 node->next = tmp; 59 } 60 61out: 62 DBG(2, "ino[0x%x] has hard links [0x%x]\n", nid, link_cnt); 63 return 0; 64} 65 66static int find_and_dec_hard_link_list(struct f2fs_sb_info *sbi, u32 nid) 67{ 68 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 69 struct hard_link_node *node = NULL, *prev = NULL; 70 71 if (fsck->hard_link_list_head == NULL) { 72 ASSERT(0); 73 return -1; 74 } 75 76 node = fsck->hard_link_list_head; 77 78 while (node && (nid < node->nid)) { 79 prev = node; 80 node = node->next; 81 } 82 83 if (node == NULL || (nid != node->nid)) { 84 ASSERT(0); 85 return -1; 86 } 87 88 /* Decrease link count */ 89 node->links = node->links - 1; 90 91 /* if link count becomes one, remove the node */ 92 if (node->links == 1) { 93 if (fsck->hard_link_list_head == node) 94 fsck->hard_link_list_head = node->next; 95 else 96 prev->next = node->next; 97 free(node); 98 } 99 100 return 0; 101 102} 103 104static int is_valid_ssa_node_blk(struct f2fs_sb_info *sbi, u32 nid, u32 blk_addr) 105{ 106 int ret = 0; 107 struct f2fs_summary sum_entry; 108 109 ret = get_sum_entry(sbi, blk_addr, &sum_entry); 110 ASSERT(ret >= 0); 111 112 if (ret == SEG_TYPE_DATA || ret == SEG_TYPE_CUR_DATA) { 113 ASSERT_MSG(0, "Summary footer is not a node segment summary\n");; 114 } else if (ret == SEG_TYPE_NODE) { 115 if (le32_to_cpu(sum_entry.nid) != nid) { 116 DBG(0, "nid [0x%x]\n", nid); 117 DBG(0, "target blk_addr [0x%x]\n", blk_addr); 118 DBG(0, "summary blk_addr [0x%lx]\n", 119 GET_SUM_BLKADDR(sbi, GET_SEGNO(sbi, blk_addr))); 120 DBG(0, "seg no / offset [0x%x / 0x%x]\n", 121 GET_SEGNO(sbi, blk_addr), OFFSET_IN_SEG(sbi, blk_addr)); 122 DBG(0, "summary_entry.nid [0x%x]\n", le32_to_cpu(sum_entry.nid)); 123 DBG(0, "--> node block's nid [0x%x]\n", nid); 124 ASSERT_MSG(0, "Invalid node seg summary\n"); 125 } 126 } else if (ret == SEG_TYPE_CUR_NODE) { 127 /* current node segment has no ssa */ 128 } else { 129 ASSERT_MSG(0, "Invalid return value of 'get_sum_entry'"); 130 } 131 132 return 1; 133} 134 135static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr, 136 u32 parent_nid, u16 idx_in_node, u8 version) 137{ 138 int ret = 0; 139 struct f2fs_summary sum_entry; 140 141 ret = get_sum_entry(sbi, blk_addr, &sum_entry); 142 ASSERT(ret == SEG_TYPE_DATA || ret == SEG_TYPE_CUR_DATA); 143 144 if (le32_to_cpu(sum_entry.nid) != parent_nid || 145 sum_entry.version != version || 146 le16_to_cpu(sum_entry.ofs_in_node) != idx_in_node) { 147 148 DBG(0, "summary_entry.nid [0x%x]\n", le32_to_cpu(sum_entry.nid)); 149 DBG(0, "summary_entry.version [0x%x]\n", sum_entry.version); 150 DBG(0, "summary_entry.ofs_in_node [0x%x]\n", le16_to_cpu(sum_entry.ofs_in_node)); 151 152 DBG(0, "parent nid [0x%x]\n", parent_nid); 153 DBG(0, "version from nat [0x%x]\n", version); 154 DBG(0, "idx in parent node [0x%x]\n", idx_in_node); 155 156 DBG(0, "Target data block addr [0x%x]\n", blk_addr); 157 ASSERT_MSG(0, "Invalid data seg summary\n"); 158 } 159 160 return 1; 161} 162 163int fsck_chk_node_blk(struct f2fs_sb_info *sbi, 164 struct f2fs_inode *inode, 165 u32 nid, 166 enum FILE_TYPE ftype, 167 enum NODE_TYPE ntype, 168 u32 *blk_cnt) 169{ 170 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 171 struct node_info ni; 172 struct f2fs_node *node_blk = NULL; 173 int ret = 0; 174 175 IS_VALID_NID(sbi, nid); 176 177 if (ftype != F2FS_FT_ORPHAN) 178 f2fs_clear_bit(nid, fsck->nat_area_bitmap); 179 180 ret = get_node_info(sbi, nid, &ni); 181 ASSERT(ret >= 0); 182 183 /* Is it reserved block? 184 * if block addresss was 0xffff,ffff,ffff,ffff 185 * it means that block was already allocated, but not stored in disk 186 */ 187 if (ni.blk_addr == NEW_ADDR) { 188 fsck->chk.valid_blk_cnt++; 189 fsck->chk.valid_node_cnt++; 190 if (ntype == TYPE_INODE) 191 fsck->chk.valid_inode_cnt++; 192 return 0; 193 } 194 195 IS_VALID_BLK_ADDR(sbi, ni.blk_addr); 196 197 is_valid_ssa_node_blk(sbi, nid, ni.blk_addr); 198 199 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->sit_area_bitmap) == 0x0) { 200 DBG(0, "SIT bitmap is 0x0. blk_addr[0x%x]\n", ni.blk_addr); 201 ASSERT(0); 202 } 203 204 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) == 0x0) { 205 fsck->chk.valid_blk_cnt++; 206 fsck->chk.valid_node_cnt++; 207 } 208 209 node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); 210 ASSERT(node_blk != NULL); 211 212 ret = dev_read_block(node_blk, ni.blk_addr); 213 ASSERT(ret >= 0); 214 215 ASSERT_MSG(nid == le32_to_cpu(node_blk->footer.nid), 216 "nid[0x%x] blk_addr[0x%x] footer.nid[0x%x]\n", 217 nid, ni.blk_addr, le32_to_cpu(node_blk->footer.nid)); 218 219 if (ntype == TYPE_INODE) { 220 ret = fsck_chk_inode_blk(sbi, 221 nid, 222 ftype, 223 node_blk, 224 blk_cnt, 225 &ni); 226 } else { 227 /* it's not inode */ 228 ASSERT(node_blk->footer.nid != node_blk->footer.ino); 229 230 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) != 0) { 231 DBG(0, "Duplicated node block. ino[0x%x][0x%x]\n", nid, ni.blk_addr); 232 ASSERT(0); 233 } 234 f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap); 235 236 switch (ntype) { 237 case TYPE_DIRECT_NODE: 238 ret = fsck_chk_dnode_blk(sbi, 239 inode, 240 nid, 241 ftype, 242 node_blk, 243 blk_cnt, 244 &ni); 245 break; 246 case TYPE_INDIRECT_NODE: 247 ret = fsck_chk_idnode_blk(sbi, 248 inode, 249 nid, 250 ftype, 251 node_blk, 252 blk_cnt); 253 break; 254 case TYPE_DOUBLE_INDIRECT_NODE: 255 ret = fsck_chk_didnode_blk(sbi, 256 inode, 257 nid, 258 ftype, 259 node_blk, 260 blk_cnt); 261 break; 262 default: 263 ASSERT(0); 264 } 265 } 266 ASSERT(ret >= 0); 267 268 free(node_blk); 269 return 0; 270} 271 272int fsck_chk_inode_blk(struct f2fs_sb_info *sbi, 273 u32 nid, 274 enum FILE_TYPE ftype, 275 struct f2fs_node *node_blk, 276 u32 *blk_cnt, 277 struct node_info *ni) 278{ 279 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 280 u32 child_cnt = 0, child_files = 0; 281 enum NODE_TYPE ntype; 282 u32 i_links = le32_to_cpu(node_blk->i.i_links); 283 u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks); 284 int idx = 0; 285 int ret = 0; 286 287 ASSERT(node_blk->footer.nid == node_blk->footer.ino); 288 ASSERT(le32_to_cpu(node_blk->footer.nid) == nid); 289 290 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) 291 fsck->chk.valid_inode_cnt++; 292 293 /* Orphan node. i_links should be 0 */ 294 if (ftype == F2FS_FT_ORPHAN) { 295 ASSERT(i_links == 0); 296 } else { 297 ASSERT(i_links > 0); 298 } 299 300 if (ftype == F2FS_FT_DIR) { 301 302 /* not included '.' & '..' */ 303 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) != 0) { 304 DBG(0, "Duplicated inode blk. ino[0x%x][0x%x]\n", nid, ni->blk_addr); 305 ASSERT(0); 306 } 307 f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); 308 309 } else { 310 311 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap) == 0x0) { 312 f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni->blk_addr), fsck->main_area_bitmap); 313 if (i_links > 1) { 314 /* First time. Create new hard link node */ 315 add_into_hard_link_list(sbi, nid, i_links); 316 fsck->chk.multi_hard_link_files++; 317 } 318 } else { 319 if (i_links <= 1) { 320 DBG(0, "Error. Node ID [0x%x]." 321 " There are one more hard links." 322 " But i_links is [0x%x]\n", 323 nid, i_links); 324 ASSERT(0); 325 } 326 327 DBG(3, "ino[0x%x] has hard links [0x%x]\n", nid, i_links); 328 ret = find_and_dec_hard_link_list(sbi, nid); 329 ASSERT(ret >= 0); 330 331 /* No need to go deep into the node */ 332 goto out; 333 } 334 } 335 336 fsck_chk_xattr_blk(sbi, nid, le32_to_cpu(node_blk->i.i_xattr_nid), blk_cnt); 337 338 if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV || 339 ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK) 340 goto check; 341 342 /* check data blocks in inode */ 343 for (idx = 0; idx < ADDRS_PER_INODE(&node_blk->i); idx++) { 344 if (le32_to_cpu(node_blk->i.i_addr[idx]) != 0) { 345 *blk_cnt = *blk_cnt + 1; 346 ret = fsck_chk_data_blk(sbi, 347 &node_blk->i, 348 le32_to_cpu(node_blk->i.i_addr[idx]), 349 &child_cnt, 350 &child_files, 351 (i_blocks == *blk_cnt), 352 ftype, 353 nid, 354 idx, 355 ni->version); 356 ASSERT(ret >= 0); 357 } 358 } 359 360 /* check node blocks in inode */ 361 for (idx = 0; idx < 5; idx++) { 362 if (idx == 0 || idx == 1) 363 ntype = TYPE_DIRECT_NODE; 364 else if (idx == 2 || idx == 3) 365 ntype = TYPE_INDIRECT_NODE; 366 else if (idx == 4) 367 ntype = TYPE_DOUBLE_INDIRECT_NODE; 368 else 369 ASSERT(0); 370 371 if (le32_to_cpu(node_blk->i.i_nid[idx]) != 0) { 372 *blk_cnt = *blk_cnt + 1; 373 ret = fsck_chk_node_blk(sbi, 374 &node_blk->i, 375 le32_to_cpu(node_blk->i.i_nid[idx]), 376 ftype, 377 ntype, 378 blk_cnt); 379 ASSERT(ret >= 0); 380 } 381 } 382check: 383 if (ftype == F2FS_FT_DIR) 384 DBG(1, "Directory Inode: ino: %x name: %s depth: %d child files: %d\n\n", 385 le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, 386 le32_to_cpu(node_blk->i.i_current_depth), child_files); 387 if (ftype == F2FS_FT_ORPHAN) 388 DBG(1, "Orphan Inode: ino: %x name: %s i_blocks: %d\n\n", 389 le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, 390 i_blocks); 391 if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || 392 (i_blocks != *blk_cnt)) { 393 print_node_info(node_blk); 394 DBG(1, "blk cnt [0x%x]\n", *blk_cnt); 395 DBG(1, "child cnt [0x%x]\n", child_cnt); 396 } 397 398 ASSERT(i_blocks == *blk_cnt); 399 if (ftype == F2FS_FT_DIR) 400 ASSERT(i_links == child_cnt); 401out: 402 return 0; 403} 404 405int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, 406 struct f2fs_inode *inode, 407 u32 nid, 408 enum FILE_TYPE ftype, 409 struct f2fs_node *node_blk, 410 u32 *blk_cnt, 411 struct node_info *ni) 412{ 413 int idx; 414 u32 child_cnt = 0, child_files = 0; 415 416 for (idx = 0; idx < ADDRS_PER_BLOCK; idx++) { 417 if (le32_to_cpu(node_blk->dn.addr[idx]) == 0x0) 418 continue; 419 *blk_cnt = *blk_cnt + 1; 420 fsck_chk_data_blk(sbi, 421 inode, 422 le32_to_cpu(node_blk->dn.addr[idx]), 423 &child_cnt, 424 &child_files, 425 le64_to_cpu(inode->i_blocks) == *blk_cnt, 426 ftype, 427 nid, 428 idx, 429 ni->version); 430 } 431 432 return 0; 433} 434 435int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, 436 struct f2fs_inode *inode, 437 u32 nid, 438 enum FILE_TYPE ftype, 439 struct f2fs_node *node_blk, 440 u32 *blk_cnt) 441{ 442 int i = 0; 443 444 for (i = 0 ; i < NIDS_PER_BLOCK; i++) { 445 if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) 446 continue; 447 *blk_cnt = *blk_cnt + 1; 448 fsck_chk_node_blk(sbi, 449 inode, 450 le32_to_cpu(node_blk->in.nid[i]), 451 ftype, 452 TYPE_DIRECT_NODE, 453 blk_cnt); 454 } 455 456 return 0; 457} 458 459int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, 460 struct f2fs_inode *inode, 461 u32 nid, 462 enum FILE_TYPE ftype, 463 struct f2fs_node *node_blk, 464 u32 *blk_cnt) 465{ 466 int i = 0; 467 468 for (i = 0; i < NIDS_PER_BLOCK; i++) { 469 if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) 470 continue; 471 *blk_cnt = *blk_cnt + 1; 472 fsck_chk_node_blk(sbi, 473 inode, 474 le32_to_cpu(node_blk->in.nid[i]), 475 ftype, 476 TYPE_INDIRECT_NODE, 477 blk_cnt); 478 } 479 480 return 0; 481} 482 483static void print_dentry(__u32 depth, __u8 *name, 484 struct f2fs_dentry_block *de_blk, int idx, int last_blk) 485{ 486 int last_de = 0; 487 int next_idx = 0; 488 int name_len; 489 int i; 490 int bit_offset; 491 492 if (config.dbg_lv != -1) 493 return; 494 495 name_len = le16_to_cpu(de_blk->dentry[idx].name_len); 496 next_idx = idx + (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; 497 498 bit_offset = find_next_bit((unsigned long *)de_blk->dentry_bitmap, 499 NR_DENTRY_IN_BLOCK, next_idx); 500 if (bit_offset >= NR_DENTRY_IN_BLOCK && last_blk) 501 last_de = 1; 502 503 if (tree_mark_size <= depth) { 504 tree_mark_size *= 2; 505 tree_mark = realloc(tree_mark, tree_mark_size); 506 } 507 508 if (last_de) 509 tree_mark[depth] = '`'; 510 else 511 tree_mark[depth] = '|'; 512 513 if (tree_mark[depth - 1] == '`') 514 tree_mark[depth - 1] = ' '; 515 516 517 for (i = 1; i < depth; i++) 518 printf("%c ", tree_mark[i]); 519 printf("%c-- %s\n", last_de ? '`' : '|', name); 520} 521 522int fsck_chk_dentry_blk(struct f2fs_sb_info *sbi, 523 struct f2fs_inode *inode, 524 u32 blk_addr, 525 u32 *child_cnt, 526 u32 *child_files, 527 int last_blk) 528{ 529 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 530 int i; 531 int ret = 0; 532 int dentries = 0; 533 u8 *name; 534 u32 hash_code; 535 u32 blk_cnt; 536 u16 name_len;; 537 538 enum FILE_TYPE ftype; 539 struct f2fs_dentry_block *de_blk; 540 541 de_blk = (struct f2fs_dentry_block *)calloc(BLOCK_SZ, 1); 542 ASSERT(de_blk != NULL); 543 544 ret = dev_read_block(de_blk, blk_addr); 545 ASSERT(ret >= 0); 546 547 fsck->dentry_depth++; 548 549 for (i = 0; i < NR_DENTRY_IN_BLOCK;) { 550 if (test_bit(i, (unsigned long *)de_blk->dentry_bitmap) == 0x0) { 551 i++; 552 continue; 553 } 554 555 name_len = le32_to_cpu(de_blk->dentry[i].name_len); 556 name = calloc(name_len + 1, 1); 557 memcpy(name, de_blk->filename[i], name_len); 558 559 hash_code = f2fs_dentry_hash((const char *)name, name_len); 560 ASSERT(le32_to_cpu(de_blk->dentry[i].hash_code) == hash_code); 561 562 ftype = de_blk->dentry[i].file_type; 563 564 /* Becareful. 'dentry.file_type' is not imode. */ 565 if (ftype == F2FS_FT_DIR) { 566 *child_cnt = *child_cnt + 1; 567 if ((name[0] == '.' && name[1] == '.' && name_len == 2) || 568 (name[0] == '.' && name_len == 1)) { 569 i++; 570 free(name); 571 continue; 572 } 573 } 574 575 DBG(2, "[%3u] - no[0x%x] name[%s] len[0x%x] ino[0x%x] type[0x%x]\n", 576 fsck->dentry_depth, i, name, name_len, 577 le32_to_cpu(de_blk->dentry[i].ino), 578 de_blk->dentry[i].file_type); 579 580 print_dentry(fsck->dentry_depth, name, de_blk, i, last_blk); 581 582 blk_cnt = 1; 583 ret = fsck_chk_node_blk(sbi, 584 NULL, 585 le32_to_cpu(de_blk->dentry[i].ino), 586 ftype, 587 TYPE_INODE, 588 &blk_cnt); 589 590 ASSERT(ret >= 0); 591 592 i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; 593 dentries++; 594 *child_files = *child_files + 1; 595 free(name); 596 } 597 598 DBG(1, "[%3d] Dentry Block [0x%x] Done : dentries:%d in %d slots (len:%d)\n\n", 599 fsck->dentry_depth, blk_addr, dentries, NR_DENTRY_IN_BLOCK, F2FS_NAME_LEN); 600 fsck->dentry_depth--; 601 602 free(de_blk); 603 return 0; 604} 605 606int fsck_chk_data_blk(struct f2fs_sb_info *sbi, 607 struct f2fs_inode *inode, 608 u32 blk_addr, 609 u32 *child_cnt, 610 u32 *child_files, 611 int last_blk, 612 enum FILE_TYPE ftype, 613 u32 parent_nid, 614 u16 idx_in_node, 615 u8 ver) 616{ 617 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 618 619 /* Is it reserved block? */ 620 if (blk_addr == NEW_ADDR) { 621 fsck->chk.valid_blk_cnt++; 622 return 0; 623 } 624 625 IS_VALID_BLK_ADDR(sbi, blk_addr); 626 627 is_valid_ssa_data_blk(sbi, blk_addr, parent_nid, idx_in_node, ver); 628 629 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->sit_area_bitmap) == 0x0) { 630 ASSERT_MSG(0, "SIT bitmap is 0x0. blk_addr[0x%x]\n", blk_addr); 631 } 632 633 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->main_area_bitmap) != 0) { 634 ASSERT_MSG(0, "Duplicated data block. pnid[0x%x] idx[0x%x] blk_addr[0x%x]\n", 635 parent_nid, idx_in_node, blk_addr); 636 } 637 f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk_addr), fsck->main_area_bitmap); 638 639 fsck->chk.valid_blk_cnt++; 640 641 if (ftype == F2FS_FT_DIR) { 642 fsck_chk_dentry_blk(sbi, 643 inode, 644 blk_addr, 645 child_cnt, 646 child_files, 647 last_blk); 648 } 649 650 return 0; 651} 652 653int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) 654{ 655 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 656 int ret = 0; 657 u32 blk_cnt = 0; 658 659 block_t start_blk, orphan_blkaddr, i, j; 660 struct f2fs_orphan_block *orphan_blk; 661 662 if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) 663 return 0; 664 665 start_blk = __start_cp_addr(sbi) + 1; 666 orphan_blkaddr = __start_sum_addr(sbi) - 1; 667 668 orphan_blk = calloc(BLOCK_SZ, 1); 669 670 for (i = 0; i < orphan_blkaddr; i++) { 671 dev_read_block(orphan_blk, start_blk + i); 672 673 for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { 674 nid_t ino = le32_to_cpu(orphan_blk->ino[j]); 675 DBG(3, "[%3ld] ino [0x%x]\n", i, ino); 676 677 /* 1) 'fsck_init' build nat_bitmap 678 * 2) 'fsck_chk_node_blk' clear nat_bitmap if exist in dentry 679 * 3) if nat_bitmap is already cleared, it means that node exist in dentry, 680 */ 681 if (f2fs_test_bit(ino, fsck->nat_area_bitmap) != 0x0) { 682 f2fs_clear_bit(ino, fsck->nat_area_bitmap); 683 } else { 684 DBG(0, "orphan inode [0x%x] exist in dentry\n", ino); 685 ASSERT(0); 686 } 687 688 DBG(1, "Orphan inode ino[0x%x]\n", ino); 689 690 blk_cnt = 1; 691 ret = fsck_chk_node_blk(sbi, 692 NULL, 693 ino, 694 F2FS_FT_ORPHAN, 695 TYPE_INODE, 696 &blk_cnt); 697 ASSERT(ret >= 0); 698 } 699 memset(orphan_blk, 0, BLOCK_SZ); 700 } 701 free(orphan_blk); 702 703 704 return 0; 705} 706 707int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino, u32 x_nid, u32 *blk_cnt) 708{ 709 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 710 struct node_info ni; 711 712 if (x_nid == 0x0) 713 return 0; 714 715 if (f2fs_test_bit(x_nid, fsck->nat_area_bitmap) != 0x0) { 716 f2fs_clear_bit(x_nid, fsck->nat_area_bitmap); 717 } else { 718 ASSERT_MSG(0, "xattr_nid duplicated [0x%x]\n", x_nid); 719 } 720 721 *blk_cnt = *blk_cnt + 1; 722 fsck->chk.valid_blk_cnt++; 723 fsck->chk.valid_node_cnt++; 724 725 ASSERT(get_node_info(sbi, x_nid, &ni) >= 0); 726 727 if (f2fs_test_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap) != 0) { 728 ASSERT_MSG(0, "Duplicated node block for x_attr. " 729 "x_nid[0x%x] block addr[0x%x]\n", 730 x_nid, ni.blk_addr); 731 } 732 f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, ni.blk_addr), fsck->main_area_bitmap); 733 734 DBG(2, "ino[0x%x] x_nid[0x%x]\n", ino, x_nid); 735 return 0; 736} 737 738int fsck_init(struct f2fs_sb_info *sbi) 739{ 740 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 741 struct f2fs_sm_info *sm_i = SM_I(sbi); 742 743 /* 744 * We build three bitmap for main/sit/nat so that may check consistency of filesystem. 745 * 1. main_area_bitmap will be used to check whether all blocks of main area is used or not. 746 * 2. nat_area_bitmap has bitmap information of used nid in NAT. 747 * 3. sit_area_bitmap has bitmap information of used main block. 748 * At Last sequence, we compare main_area_bitmap with sit_area_bitmap. 749 */ 750 fsck->nr_main_blks = sm_i->main_segments << sbi->log_blocks_per_seg; 751 fsck->main_area_bitmap_sz = (fsck->nr_main_blks + 7) / 8; 752 fsck->main_area_bitmap = calloc(fsck->main_area_bitmap_sz, 1); 753 ASSERT(fsck->main_area_bitmap != NULL); 754 755 build_nat_area_bitmap(sbi); 756 757 build_sit_area_bitmap(sbi); 758 759 tree_mark = calloc(tree_mark_size, 1); 760 return 0; 761} 762 763int fsck_verify(struct f2fs_sb_info *sbi) 764{ 765 int i = 0; 766 int ret = 0; 767 u32 nr_unref_nid = 0; 768 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 769 struct hard_link_node *node = NULL; 770 771 printf("\n"); 772 773 for (i = 0; i < fsck->nr_nat_entries; i++) { 774 if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) { 775 printf("NID[0x%x] is unreachable\n", i); 776 nr_unref_nid++; 777 } 778 } 779 780 if (fsck->hard_link_list_head != NULL) { 781 node = fsck->hard_link_list_head; 782 while (node) { 783 printf("NID[0x%x] has [0x%x] more unreachable links\n", 784 node->nid, node->links); 785 node = node->next; 786 } 787 } 788 789 printf("[FSCK] Unreachable nat entries "); 790 if (nr_unref_nid == 0x0) { 791 printf(" [Ok..] [0x%x]\n", nr_unref_nid); 792 } else { 793 printf(" [Fail] [0x%x]\n", nr_unref_nid); 794 ret = EXIT_ERR_CODE; 795 } 796 797 printf("[FSCK] SIT valid block bitmap checking "); 798 if (memcmp(fsck->sit_area_bitmap, fsck->main_area_bitmap, fsck->sit_area_bitmap_sz) == 0x0) { 799 printf("[Ok..]\n"); 800 } else { 801 printf("[Fail]\n"); 802 ret = EXIT_ERR_CODE; 803 } 804 805 printf("[FSCK] Hard link checking for regular file "); 806 if (fsck->hard_link_list_head == NULL) { 807 printf(" [Ok..] [0x%x]\n", fsck->chk.multi_hard_link_files); 808 } else { 809 printf(" [Fail] [0x%x]\n", fsck->chk.multi_hard_link_files); 810 ret = EXIT_ERR_CODE; 811 } 812 813 printf("[FSCK] valid_block_count matching with CP "); 814 if (sbi->total_valid_block_count == fsck->chk.valid_blk_cnt) { 815 printf(" [Ok..] [0x%lx]\n", fsck->chk.valid_blk_cnt); 816 } else { 817 printf(" [Fail] [0x%lx]\n", fsck->chk.valid_blk_cnt); 818 ret = EXIT_ERR_CODE; 819 } 820 821 printf("[FSCK] valid_node_count matcing with CP (de lookup) "); 822 if (sbi->total_valid_node_count == fsck->chk.valid_node_cnt) { 823 printf(" [Ok..] [0x%x]\n", fsck->chk.valid_node_cnt); 824 } else { 825 printf(" [Fail] [0x%x]\n", fsck->chk.valid_node_cnt); 826 ret = EXIT_ERR_CODE; 827 } 828 829 printf("[FSCK] valid_node_count matcing with CP (nat lookup) "); 830 if (sbi->total_valid_node_count == fsck->chk.valid_nat_entry_cnt) { 831 printf(" [Ok..] [0x%x]\n", fsck->chk.valid_nat_entry_cnt); 832 } else { 833 printf(" [Fail] [0x%x]\n", fsck->chk.valid_nat_entry_cnt); 834 ret = EXIT_ERR_CODE; 835 } 836 837 printf("[FSCK] valid_inode_count matched with CP "); 838 if (sbi->total_valid_inode_count == fsck->chk.valid_inode_cnt) { 839 printf(" [Ok..] [0x%x]\n", fsck->chk.valid_inode_cnt); 840 } else { 841 printf(" [Fail] [0x%x]\n", fsck->chk.valid_inode_cnt); 842 ret = EXIT_ERR_CODE; 843 } 844 845 return ret; 846} 847 848void fsck_free(struct f2fs_sb_info *sbi) 849{ 850 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 851 if (fsck->main_area_bitmap) 852 free(fsck->main_area_bitmap); 853 854 if (fsck->nat_area_bitmap) 855 free(fsck->nat_area_bitmap); 856 857 if (fsck->sit_area_bitmap) 858 free(fsck->sit_area_bitmap); 859 860 if (tree_mark) 861 free(tree_mark); 862} 863