f2fs: fix f2fs_write_meta_page at no checkpoint status
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Wed, 5 Feb 2014 04:03:57 +0000 (13:03 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Mon, 17 Feb 2014 05:58:53 +0000 (14:58 +0900)
If f2fs entered errorneous checkpoint status, it should skip writing meta
pages instead of redirtying the pages out.
Otherwise, it cannot unmount the partition even though f2fs is under read-only
status.

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
fs/f2fs/checkpoint.c
fs/f2fs/gc.c

index 293d0486a40f7e8560b25d012a7a2398ef4e955c..8f5dff1989a83c382627458a7cb65a825abab371 100644 (file)
@@ -81,17 +81,18 @@ static int f2fs_write_meta_page(struct page *page,
        struct inode *inode = page->mapping->host;
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
-       /* Should not write any meta pages, if any IO error was occurred */
-       if (unlikely(sbi->por_doing ||
-                       is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+       if (unlikely(sbi->por_doing))
                goto redirty_out;
-
        if (wbc->for_reclaim)
                goto redirty_out;
 
-       wait_on_page_writeback(page);
+       /* Should not write any meta pages, if any IO error was occurred */
+       if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+               goto no_write;
 
+       wait_on_page_writeback(page);
        write_meta_page(sbi, page);
+no_write:
        dec_page_count(sbi, F2FS_DIRTY_META);
        unlock_page(page);
        return 0;
@@ -148,10 +149,22 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
 
                for (i = 0; i < nr_pages; i++) {
                        struct page *page = pvec.pages[i];
+
                        lock_page(page);
-                       f2fs_bug_on(page->mapping != mapping);
-                       f2fs_bug_on(!PageDirty(page));
-                       clear_page_dirty_for_io(page);
+
+                       if (unlikely(page->mapping != mapping)) {
+continue_unlock:
+                               unlock_page(page);
+                               continue;
+                       }
+                       if (!PageDirty(page)) {
+                               /* someone wrote it for us */
+                               goto continue_unlock;
+                       }
+
+                       if (!clear_page_dirty_for_io(page))
+                               goto continue_unlock;
+
                        if (f2fs_write_meta_page(page, &wbc)) {
                                unlock_page(page);
                                break;
index ea0371e854b4e0244537cf3d33f5f17e147e8a25..b0f57628fe5564f09e0343067c5b0892bee205cc 100644 (file)
@@ -701,6 +701,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi)
 gc_more:
        if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE)))
                goto stop;
+       if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+               goto stop;
 
        if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) {
                gc_type = FG_GC;