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....@samsung.com>
---
 fs/f2fs/checkpoint.c | 29 +++++++++++++++++++++--------
 fs/f2fs/gc.c         |  2 ++
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 293d048..8f5dff1 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -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;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ea0371e..b0f5762 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -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;
-- 
1.8.4.474.g128a96c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to