aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-07-25 18:47:25 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2014-07-30 17:13:35 -0400
commitcf2271e781cb16e1ca22be920010c2b64d90c338 (patch)
treee5326d4d03ed5b66359faf41a00b49416d180341 /fs/f2fs
parent61e0f2d0a5f2cddf7cd96fa8cb7fe53a1e5e325d (diff)
f2fs: avoid retrying wrong recovery routine when error was occurred
This patch eliminates the propagation of recovery errors to the next mount. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/checkpoint.c3
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/recovery.c20
-rw-r--r--fs/f2fs/segment.c5
4 files changed, 23 insertions, 7 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 26b94bbc826c..cea20b810f44 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -796,6 +796,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
796static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) 796static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
797{ 797{
798 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 798 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
799 struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
799 nid_t last_nid = 0; 800 nid_t last_nid = 0;
800 block_t start_blk; 801 block_t start_blk;
801 struct page *cp_page; 802 struct page *cp_page;
@@ -809,7 +810,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
809 * This avoids to conduct wrong roll-forward operations and uses 810 * This avoids to conduct wrong roll-forward operations and uses
810 * metapages, so should be called prior to sync_meta_pages below. 811 * metapages, so should be called prior to sync_meta_pages below.
811 */ 812 */
812 discard_next_dnode(sbi); 813 discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg));
813 814
814 /* Flush all the NAT/SIT pages */ 815 /* Flush all the NAT/SIT pages */
815 while (get_pages(sbi, F2FS_DIRTY_META)) 816 while (get_pages(sbi, F2FS_DIRTY_META))
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 475f97ca49ae..14b9f746d5b3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1225,7 +1225,7 @@ void destroy_flush_cmd_control(struct f2fs_sb_info *);
1225void invalidate_blocks(struct f2fs_sb_info *, block_t); 1225void invalidate_blocks(struct f2fs_sb_info *, block_t);
1226void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t); 1226void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t);
1227void clear_prefree_segments(struct f2fs_sb_info *); 1227void clear_prefree_segments(struct f2fs_sb_info *);
1228void discard_next_dnode(struct f2fs_sb_info *); 1228void discard_next_dnode(struct f2fs_sb_info *, block_t);
1229int npages_for_summary_flush(struct f2fs_sb_info *); 1229int npages_for_summary_flush(struct f2fs_sb_info *);
1230void allocate_new_segments(struct f2fs_sb_info *); 1230void allocate_new_segments(struct f2fs_sb_info *);
1231struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); 1231struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index a112368a4a86..b2aa53b99f64 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -434,7 +434,9 @@ next:
434 434
435int recover_fsync_data(struct f2fs_sb_info *sbi) 435int recover_fsync_data(struct f2fs_sb_info *sbi)
436{ 436{
437 struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
437 struct list_head inode_list; 438 struct list_head inode_list;
439 block_t blkaddr;
438 int err; 440 int err;
439 bool need_writecp = false; 441 bool need_writecp = false;
440 442
@@ -447,6 +449,9 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
447 449
448 /* step #1: find fsynced inode numbers */ 450 /* step #1: find fsynced inode numbers */
449 sbi->por_doing = true; 451 sbi->por_doing = true;
452
453 blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
454
450 err = find_fsync_dnodes(sbi, &inode_list); 455 err = find_fsync_dnodes(sbi, &inode_list);
451 if (err) 456 if (err)
452 goto out; 457 goto out;
@@ -462,8 +467,21 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
462out: 467out:
463 destroy_fsync_dnodes(&inode_list); 468 destroy_fsync_dnodes(&inode_list);
464 kmem_cache_destroy(fsync_entry_slab); 469 kmem_cache_destroy(fsync_entry_slab);
470
471 if (err) {
472 truncate_inode_pages_final(NODE_MAPPING(sbi));
473 truncate_inode_pages_final(META_MAPPING(sbi));
474 }
475
465 sbi->por_doing = false; 476 sbi->por_doing = false;
466 if (!err && need_writecp) 477 if (err) {
478 discard_next_dnode(sbi, blkaddr);
479
480 /* Flush all the NAT/SIT pages */
481 while (get_pages(sbi, F2FS_DIRTY_META))
482 sync_meta_pages(sbi, META, LONG_MAX);
483 } else if (need_writecp) {
467 write_checkpoint(sbi, false); 484 write_checkpoint(sbi, false);
485 }
468 return err; 486 return err;
469} 487}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 9fce0f47eb35..e016b97be2ac 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -379,11 +379,8 @@ static int f2fs_issue_discard(struct f2fs_sb_info *sbi,
379 return blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0); 379 return blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0);
380} 380}
381 381
382void discard_next_dnode(struct f2fs_sb_info *sbi) 382void discard_next_dnode(struct f2fs_sb_info *sbi, block_t blkaddr)
383{ 383{
384 struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
385 block_t blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
386
387 if (f2fs_issue_discard(sbi, blkaddr, 1)) { 384 if (f2fs_issue_discard(sbi, blkaddr, 1)) {
388 struct page *page = grab_meta_page(sbi, blkaddr); 385 struct page *page = grab_meta_page(sbi, blkaddr);
389 /* zero-filled page */ 386 /* zero-filled page */