]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
f2fs: handle writepage correctly
authorJaegeuk Kim <jaegeuk@kernel.org>
Mon, 30 May 2016 04:18:23 +0000 (21:18 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 3 Jun 2016 01:05:24 +0000 (18:05 -0700)
Previously, f2fs_write_data_pages() calls __f2fs_writepage() which calls
f2fs_write_data_page().
If f2fs_write_data_page() returns AOP_WRITEPAGE_ACTIVATE, __f2fs_writepage()
calls mapping_set_error(). But, this should not happen at every time, since
sometimes f2fs_write_data_page() tries to skip writing pages without error.
For example, volatile_write() gives EIO all the time, as Shuoran Liu pointed
out.

Reported-by: Shuoran Liu <liushuoran@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c

index 5dcd8dbe20640e9f5e79bb840aec704339ee4055..c9d6fe28ae1e3dad715850e4fc222073c86c7e35 100644 (file)
@@ -1241,20 +1241,18 @@ write:
                        available_free_memory(sbi, BASE_CHECK))))
                goto redirty_out;
 
-       /* Dentry blocks are controlled by checkpoint */
-       if (S_ISDIR(inode->i_mode)) {
-               if (unlikely(f2fs_cp_error(sbi)))
-                       goto redirty_out;
-               err = do_write_data_page(&fio);
-               goto done;
-       }
-
        /* we should bypass data pages to proceed the kworkder jobs */
        if (unlikely(f2fs_cp_error(sbi))) {
                SetPageError(page);
                goto out;
        }
 
+       /* Dentry blocks are controlled by checkpoint */
+       if (S_ISDIR(inode->i_mode)) {
+               err = do_write_data_page(&fio);
+               goto done;
+       }
+
        if (!wbc->for_reclaim)
                need_balance_fs = true;
        else if (has_not_enough_free_secs(sbi, 0))
@@ -1294,16 +1292,8 @@ out:
 
 redirty_out:
        redirty_page_for_writepage(wbc, page);
-       return AOP_WRITEPAGE_ACTIVATE;
-}
-
-static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
-                       void *data)
-{
-       struct address_space *mapping = data;
-       int ret = mapping->a_ops->writepage(page, wbc);
-       mapping_set_error(mapping, ret);
-       return ret;
+       unlock_page(page);
+       return err;
 }
 
 /*
@@ -1312,8 +1302,7 @@ static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
  * warm/hot data page.
  */
 static int f2fs_write_cache_pages(struct address_space *mapping,
-                       struct writeback_control *wbc, writepage_t writepage,
-                       void *data)
+                                       struct writeback_control *wbc)
 {
        int ret = 0;
        int done = 0;
@@ -1395,16 +1384,11 @@ continue_unlock:
                        if (!clear_page_dirty_for_io(page))
                                goto continue_unlock;
 
-                       ret = (*writepage)(page, wbc, data);
+                       ret = mapping->a_ops->writepage(page, wbc);
                        if (unlikely(ret)) {
-                               if (ret == AOP_WRITEPAGE_ACTIVATE) {
-                                       unlock_page(page);
-                                       ret = 0;
-                               } else {
-                                       done_index = page->index + 1;
-                                       done = 1;
-                                       break;
-                               }
+                               done_index = page->index + 1;
+                               done = 1;
+                               break;
                        }
 
                        if (--wbc->nr_to_write <= 0 &&
@@ -1459,7 +1443,7 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 
        trace_f2fs_writepages(mapping->host, wbc, DATA);
 
-       ret = f2fs_write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
+       ret = f2fs_write_cache_pages(mapping, wbc);
        /*
         * if some pages were truncated, we cannot guarantee its mapping->host
         * to detect pending bios.