recovery.c (27fd38c5226ed0f1712d071880fa8e739eb78650) | recovery.c (41382ec43255b502321c3c27f1347efeb3279290) |
---|---|
1/* 2 * fs/f2fs/recovery.c 3 * 4 * Copyright (c) 2012 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 --- 35 unchanged lines hidden (view full) --- 44 * -> If f2fs_iget fails, then goto next to find inode(DF). 45 * But it will fail due to no inode(DF). 46 */ 47 48static struct kmem_cache *fsync_entry_slab; 49 50bool space_for_roll_forward(struct f2fs_sb_info *sbi) 51{ | 1/* 2 * fs/f2fs/recovery.c 3 * 4 * Copyright (c) 2012 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 --- 35 unchanged lines hidden (view full) --- 44 * -> If f2fs_iget fails, then goto next to find inode(DF). 45 * But it will fail due to no inode(DF). 46 */ 47 48static struct kmem_cache *fsync_entry_slab; 49 50bool space_for_roll_forward(struct f2fs_sb_info *sbi) 51{ |
52 if (sbi->last_valid_block_count + sbi->alloc_valid_block_count 53 > sbi->user_block_count) | 52 s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count); 53 54 if (sbi->last_valid_block_count + nalloc > sbi->user_block_count) |
54 return false; 55 return true; 56} 57 58static struct fsync_inode_entry *get_fsync_inode(struct list_head *head, 59 nid_t ino) 60{ 61 struct fsync_inode_entry *entry; 62 63 list_for_each_entry(entry, head, list) 64 if (entry->inode->i_ino == ino) 65 return entry; 66 67 return NULL; 68} 69 | 55 return false; 56 return true; 57} 58 59static struct fsync_inode_entry *get_fsync_inode(struct list_head *head, 60 nid_t ino) 61{ 62 struct fsync_inode_entry *entry; 63 64 list_for_each_entry(entry, head, list) 65 if (entry->inode->i_ino == ino) 66 return entry; 67 68 return NULL; 69} 70 |
70static int recover_dentry(struct inode *inode, struct page *ipage) | 71static struct fsync_inode_entry *add_fsync_inode(struct list_head *head, 72 struct inode *inode) |
71{ | 73{ |
74 struct fsync_inode_entry *entry; 75 76 entry = kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO); 77 if (!entry) 78 return NULL; 79 80 entry->inode = inode; 81 list_add_tail(&entry->list, head); 82 83 return entry; 84} 85 86static void del_fsync_inode(struct fsync_inode_entry *entry) 87{ 88 iput(entry->inode); 89 list_del(&entry->list); 90 kmem_cache_free(fsync_entry_slab, entry); 91} 92 93static int recover_dentry(struct inode *inode, struct page *ipage, 94 struct list_head *dir_list) 95{ |
|
72 struct f2fs_inode *raw_inode = F2FS_INODE(ipage); 73 nid_t pino = le32_to_cpu(raw_inode->i_pino); 74 struct f2fs_dir_entry *de; 75 struct qstr name; 76 struct page *page; 77 struct inode *dir, *einode; | 96 struct f2fs_inode *raw_inode = F2FS_INODE(ipage); 97 nid_t pino = le32_to_cpu(raw_inode->i_pino); 98 struct f2fs_dir_entry *de; 99 struct qstr name; 100 struct page *page; 101 struct inode *dir, *einode; |
102 struct fsync_inode_entry *entry; |
|
78 int err = 0; 79 | 103 int err = 0; 104 |
80 dir = f2fs_iget(inode->i_sb, pino); 81 if (IS_ERR(dir)) { 82 err = PTR_ERR(dir); 83 goto out; | 105 entry = get_fsync_inode(dir_list, pino); 106 if (!entry) { 107 dir = f2fs_iget(inode->i_sb, pino); 108 if (IS_ERR(dir)) { 109 err = PTR_ERR(dir); 110 goto out; 111 } 112 113 entry = add_fsync_inode(dir_list, dir); 114 if (!entry) { 115 err = -ENOMEM; 116 iput(dir); 117 goto out; 118 } |
84 } 85 | 119 } 120 |
86 if (file_enc_name(inode)) { 87 iput(dir); | 121 dir = entry->inode; 122 123 if (file_enc_name(inode)) |
88 return 0; | 124 return 0; |
89 } | |
90 91 name.len = le32_to_cpu(raw_inode->i_namelen); 92 name.name = raw_inode->i_name; 93 94 if (unlikely(name.len > F2FS_NAME_LEN)) { 95 WARN_ON(1); 96 err = -ENAMETOOLONG; | 125 126 name.len = le32_to_cpu(raw_inode->i_namelen); 127 name.name = raw_inode->i_name; 128 129 if (unlikely(name.len > F2FS_NAME_LEN)) { 130 WARN_ON(1); 131 err = -ENAMETOOLONG; |
97 goto out_err; | 132 goto out; |
98 } 99retry: 100 de = f2fs_find_entry(dir, &name, &page); 101 if (de && inode->i_ino == le32_to_cpu(de->ino)) 102 goto out_unmap_put; 103 104 if (de) { 105 einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); --- 9 unchanged lines hidden (view full) --- 115 iput(einode); 116 goto out_unmap_put; 117 } 118 f2fs_delete_entry(de, page, dir, einode); 119 iput(einode); 120 goto retry; 121 } 122 err = __f2fs_add_link(dir, &name, inode, inode->i_ino, inode->i_mode); | 133 } 134retry: 135 de = f2fs_find_entry(dir, &name, &page); 136 if (de && inode->i_ino == le32_to_cpu(de->ino)) 137 goto out_unmap_put; 138 139 if (de) { 140 einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); --- 9 unchanged lines hidden (view full) --- 150 iput(einode); 151 goto out_unmap_put; 152 } 153 f2fs_delete_entry(de, page, dir, einode); 154 iput(einode); 155 goto retry; 156 } 157 err = __f2fs_add_link(dir, &name, inode, inode->i_ino, inode->i_mode); |
123 if (err) 124 goto out_err; | |
125 | 158 |
126 if (is_inode_flag_set(F2FS_I(dir), FI_DELAY_IPUT)) { 127 iput(dir); 128 } else { 129 add_dirty_dir_inode(dir); 130 set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); 131 } 132 | |
133 goto out; 134 135out_unmap_put: 136 f2fs_dentry_kunmap(dir, page); 137 f2fs_put_page(page, 0); | 159 goto out; 160 161out_unmap_put: 162 f2fs_dentry_kunmap(dir, page); 163 f2fs_put_page(page, 0); |
138out_err: 139 iput(dir); | |
140out: 141 f2fs_msg(inode->i_sb, KERN_NOTICE, 142 "%s: ino = %x, name = %s, dir = %lx, err = %d", 143 __func__, ino_of_node(ipage), raw_inode->i_name, 144 IS_ERR(dir) ? 0 : dir->i_ino, err); 145 return err; 146} 147 --- 45 unchanged lines hidden (view full) --- 193 194 return true; 195} 196 197static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) 198{ 199 unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); 200 struct curseg_info *curseg; | 164out: 165 f2fs_msg(inode->i_sb, KERN_NOTICE, 166 "%s: ino = %x, name = %s, dir = %lx, err = %d", 167 __func__, ino_of_node(ipage), raw_inode->i_name, 168 IS_ERR(dir) ? 0 : dir->i_ino, err); 169 return err; 170} 171 --- 45 unchanged lines hidden (view full) --- 217 218 return true; 219} 220 221static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) 222{ 223 unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); 224 struct curseg_info *curseg; |
225 struct inode *inode; |
|
201 struct page *page = NULL; 202 block_t blkaddr; 203 int err = 0; 204 205 /* get node pages in the current segment */ 206 curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 207 blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 208 | 226 struct page *page = NULL; 227 block_t blkaddr; 228 int err = 0; 229 230 /* get node pages in the current segment */ 231 curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 232 blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 233 |
209 ra_meta_pages(sbi, blkaddr, 1, META_POR, true); 210 | |
211 while (1) { 212 struct fsync_inode_entry *entry; 213 214 if (!is_valid_blkaddr(sbi, blkaddr, META_POR)) 215 return 0; 216 217 page = get_tmp_page(sbi, blkaddr); 218 --- 9 unchanged lines hidden (view full) --- 228 goto next; 229 } else { 230 if (IS_INODE(page) && is_dent_dnode(page)) { 231 err = recover_inode_page(sbi, page); 232 if (err) 233 break; 234 } 235 | 234 while (1) { 235 struct fsync_inode_entry *entry; 236 237 if (!is_valid_blkaddr(sbi, blkaddr, META_POR)) 238 return 0; 239 240 page = get_tmp_page(sbi, blkaddr); 241 --- 9 unchanged lines hidden (view full) --- 251 goto next; 252 } else { 253 if (IS_INODE(page) && is_dent_dnode(page)) { 254 err = recover_inode_page(sbi, page); 255 if (err) 256 break; 257 } 258 |
236 /* add this fsync inode to the list */ 237 entry = kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO); 238 if (!entry) { 239 err = -ENOMEM; 240 break; 241 } | |
242 /* 243 * CP | dnode(F) | inode(DF) 244 * For this case, we should not give up now. 245 */ | 259 /* 260 * CP | dnode(F) | inode(DF) 261 * For this case, we should not give up now. 262 */ |
246 entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); 247 if (IS_ERR(entry->inode)) { 248 err = PTR_ERR(entry->inode); 249 kmem_cache_free(fsync_entry_slab, entry); | 263 inode = f2fs_iget(sbi->sb, ino_of_node(page)); 264 if (IS_ERR(inode)) { 265 err = PTR_ERR(inode); |
250 if (err == -ENOENT) { 251 err = 0; 252 goto next; 253 } 254 break; 255 } | 266 if (err == -ENOENT) { 267 err = 0; 268 goto next; 269 } 270 break; 271 } |
256 list_add_tail(&entry->list, head); | 272 273 /* add this fsync inode to the list */ 274 entry = add_fsync_inode(head, inode); 275 if (!entry) { 276 err = -ENOMEM; 277 iput(inode); 278 break; 279 } |
257 } 258 entry->blkaddr = blkaddr; 259 | 280 } 281 entry->blkaddr = blkaddr; 282 |
260 if (IS_INODE(page)) { 261 entry->last_inode = blkaddr; 262 if (is_dent_dnode(page)) 263 entry->last_dentry = blkaddr; 264 } | 283 if (IS_INODE(page) && is_dent_dnode(page)) 284 entry->last_dentry = blkaddr; |
265next: 266 /* check next segment */ 267 blkaddr = next_blkaddr_of_node(page); 268 f2fs_put_page(page, 1); 269 270 ra_meta_pages_cond(sbi, blkaddr); 271 } 272 f2fs_put_page(page, 1); 273 return err; 274} 275 276static void destroy_fsync_dnodes(struct list_head *head) 277{ 278 struct fsync_inode_entry *entry, *tmp; 279 | 285next: 286 /* check next segment */ 287 blkaddr = next_blkaddr_of_node(page); 288 f2fs_put_page(page, 1); 289 290 ra_meta_pages_cond(sbi, blkaddr); 291 } 292 f2fs_put_page(page, 1); 293 return err; 294} 295 296static void destroy_fsync_dnodes(struct list_head *head) 297{ 298 struct fsync_inode_entry *entry, *tmp; 299 |
280 list_for_each_entry_safe(entry, tmp, head, list) { 281 iput(entry->inode); 282 list_del(&entry->list); 283 kmem_cache_free(fsync_entry_slab, entry); 284 } | 300 list_for_each_entry_safe(entry, tmp, head, list) 301 del_fsync_inode(entry); |
285} 286 287static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, 288 block_t blkaddr, struct dnode_of_data *dn) 289{ 290 struct seg_entry *sentry; 291 unsigned int segno = GET_SEGNO(sbi, blkaddr); 292 unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); --- 146 unchanged lines hidden (view full) --- 439 } 440 441 /* 442 * dest is reserved block, invalidate src block 443 * and then reserve one new block in dnode page. 444 */ 445 if (dest == NEW_ADDR) { 446 truncate_data_blocks_range(&dn, 1); | 302} 303 304static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, 305 block_t blkaddr, struct dnode_of_data *dn) 306{ 307 struct seg_entry *sentry; 308 unsigned int segno = GET_SEGNO(sbi, blkaddr); 309 unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); --- 146 unchanged lines hidden (view full) --- 456 } 457 458 /* 459 * dest is reserved block, invalidate src block 460 * and then reserve one new block in dnode page. 461 */ 462 if (dest == NEW_ADDR) { 463 truncate_data_blocks_range(&dn, 1); |
447 err = reserve_new_block(&dn); 448 f2fs_bug_on(sbi, err); | 464 reserve_new_block(&dn); |
449 continue; 450 } 451 452 /* dest is valid block, try to recover from src to dest */ 453 if (is_valid_blkaddr(sbi, dest, META_POR)) { 454 455 if (src == NULL_ADDR) { 456 err = reserve_new_block(&dn); --- 24 unchanged lines hidden (view full) --- 481 f2fs_put_dnode(&dn); 482out: 483 f2fs_msg(sbi->sb, KERN_NOTICE, 484 "recover_data: ino = %lx, recovered = %d blocks, err = %d", 485 inode->i_ino, recovered, err); 486 return err; 487} 488 | 465 continue; 466 } 467 468 /* dest is valid block, try to recover from src to dest */ 469 if (is_valid_blkaddr(sbi, dest, META_POR)) { 470 471 if (src == NULL_ADDR) { 472 err = reserve_new_block(&dn); --- 24 unchanged lines hidden (view full) --- 497 f2fs_put_dnode(&dn); 498out: 499 f2fs_msg(sbi->sb, KERN_NOTICE, 500 "recover_data: ino = %lx, recovered = %d blocks, err = %d", 501 inode->i_ino, recovered, err); 502 return err; 503} 504 |
489static int recover_data(struct f2fs_sb_info *sbi, struct list_head *head) | 505static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, 506 struct list_head *dir_list) |
490{ 491 unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); 492 struct curseg_info *curseg; 493 struct page *page = NULL; 494 int err = 0; 495 block_t blkaddr; 496 497 /* get node pages in the current segment */ --- 10 unchanged lines hidden (view full) --- 508 509 page = get_tmp_page(sbi, blkaddr); 510 511 if (cp_ver != cpver_of_node(page)) { 512 f2fs_put_page(page, 1); 513 break; 514 } 515 | 507{ 508 unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); 509 struct curseg_info *curseg; 510 struct page *page = NULL; 511 int err = 0; 512 block_t blkaddr; 513 514 /* get node pages in the current segment */ --- 10 unchanged lines hidden (view full) --- 525 526 page = get_tmp_page(sbi, blkaddr); 527 528 if (cp_ver != cpver_of_node(page)) { 529 f2fs_put_page(page, 1); 530 break; 531 } 532 |
516 entry = get_fsync_inode(head, ino_of_node(page)); | 533 entry = get_fsync_inode(inode_list, ino_of_node(page)); |
517 if (!entry) 518 goto next; 519 /* 520 * inode(x) | CP | inode(x) | dnode(F) 521 * In this case, we can lose the latest inode(x). 522 * So, call recover_inode for the inode update. 523 */ | 534 if (!entry) 535 goto next; 536 /* 537 * inode(x) | CP | inode(x) | dnode(F) 538 * In this case, we can lose the latest inode(x). 539 * So, call recover_inode for the inode update. 540 */ |
524 if (entry->last_inode == blkaddr) | 541 if (IS_INODE(page)) |
525 recover_inode(entry->inode, page); 526 if (entry->last_dentry == blkaddr) { | 542 recover_inode(entry->inode, page); 543 if (entry->last_dentry == blkaddr) { |
527 err = recover_dentry(entry->inode, page); | 544 err = recover_dentry(entry->inode, page, dir_list); |
528 if (err) { 529 f2fs_put_page(page, 1); 530 break; 531 } 532 } 533 err = do_recover_data(sbi, entry->inode, page, blkaddr); 534 if (err) { 535 f2fs_put_page(page, 1); 536 break; 537 } 538 | 545 if (err) { 546 f2fs_put_page(page, 1); 547 break; 548 } 549 } 550 err = do_recover_data(sbi, entry->inode, page, blkaddr); 551 if (err) { 552 f2fs_put_page(page, 1); 553 break; 554 } 555 |
539 if (entry->blkaddr == blkaddr) { 540 iput(entry->inode); 541 list_del(&entry->list); 542 kmem_cache_free(fsync_entry_slab, entry); 543 } | 556 if (entry->blkaddr == blkaddr) 557 del_fsync_inode(entry); |
544next: 545 /* check next segment */ 546 blkaddr = next_blkaddr_of_node(page); 547 f2fs_put_page(page, 1); 548 } 549 if (!err) 550 allocate_new_segments(sbi); 551 return err; 552} 553 | 558next: 559 /* check next segment */ 560 blkaddr = next_blkaddr_of_node(page); 561 f2fs_put_page(page, 1); 562 } 563 if (!err) 564 allocate_new_segments(sbi); 565 return err; 566} 567 |
554int recover_fsync_data(struct f2fs_sb_info *sbi) | 568int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) |
555{ 556 struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 557 struct list_head inode_list; | 569{ 570 struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 571 struct list_head inode_list; |
572 struct list_head dir_list; |
|
558 block_t blkaddr; 559 int err; | 573 block_t blkaddr; 574 int err; |
575 int ret = 0; |
|
560 bool need_writecp = false; 561 562 fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", 563 sizeof(struct fsync_inode_entry)); 564 if (!fsync_entry_slab) 565 return -ENOMEM; 566 567 INIT_LIST_HEAD(&inode_list); | 576 bool need_writecp = false; 577 578 fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", 579 sizeof(struct fsync_inode_entry)); 580 if (!fsync_entry_slab) 581 return -ENOMEM; 582 583 INIT_LIST_HEAD(&inode_list); |
584 INIT_LIST_HEAD(&dir_list); |
|
568 569 /* prevent checkpoint */ 570 mutex_lock(&sbi->cp_mutex); 571 572 blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 573 574 /* step #1: find fsynced inode numbers */ 575 err = find_fsync_dnodes(sbi, &inode_list); | 585 586 /* prevent checkpoint */ 587 mutex_lock(&sbi->cp_mutex); 588 589 blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 590 591 /* step #1: find fsynced inode numbers */ 592 err = find_fsync_dnodes(sbi, &inode_list); |
576 if (err) | 593 if (err || list_empty(&inode_list)) |
577 goto out; 578 | 594 goto out; 595 |
579 if (list_empty(&inode_list)) | 596 if (check_only) { 597 ret = 1; |
580 goto out; | 598 goto out; |
599 } |
|
581 582 need_writecp = true; 583 584 /* step #2: recover data */ | 600 601 need_writecp = true; 602 603 /* step #2: recover data */ |
585 err = recover_data(sbi, &inode_list); | 604 err = recover_data(sbi, &inode_list, &dir_list); |
586 if (!err) 587 f2fs_bug_on(sbi, !list_empty(&inode_list)); 588out: 589 destroy_fsync_dnodes(&inode_list); | 605 if (!err) 606 f2fs_bug_on(sbi, !list_empty(&inode_list)); 607out: 608 destroy_fsync_dnodes(&inode_list); |
590 kmem_cache_destroy(fsync_entry_slab); | |
591 592 /* truncate meta pages to be used by the recovery */ 593 truncate_inode_pages_range(META_MAPPING(sbi), 594 (loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1); 595 596 if (err) { 597 truncate_inode_pages_final(NODE_MAPPING(sbi)); 598 truncate_inode_pages_final(META_MAPPING(sbi)); --- 21 unchanged lines hidden (view full) --- 620 struct cp_control cpc = { 621 .reason = CP_RECOVERY, 622 }; 623 mutex_unlock(&sbi->cp_mutex); 624 err = write_checkpoint(sbi, &cpc); 625 } else { 626 mutex_unlock(&sbi->cp_mutex); 627 } | 609 610 /* truncate meta pages to be used by the recovery */ 611 truncate_inode_pages_range(META_MAPPING(sbi), 612 (loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1); 613 614 if (err) { 615 truncate_inode_pages_final(NODE_MAPPING(sbi)); 616 truncate_inode_pages_final(META_MAPPING(sbi)); --- 21 unchanged lines hidden (view full) --- 638 struct cp_control cpc = { 639 .reason = CP_RECOVERY, 640 }; 641 mutex_unlock(&sbi->cp_mutex); 642 err = write_checkpoint(sbi, &cpc); 643 } else { 644 mutex_unlock(&sbi->cp_mutex); 645 } |
628 return err; | 646 647 destroy_fsync_dnodes(&dir_list); 648 kmem_cache_destroy(fsync_entry_slab); 649 return ret ? ret: err; |
629} | 650} |