f2fs: handle writepage correctly
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>
This commit is contained in:
Родитель
eb4246dc12
Коммит
b230e6cabf
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче