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:
parent
eb4246dc12
commit
b230e6cabf
@ -1241,20 +1241,18 @@ write:
|
|||||||
available_free_memory(sbi, BASE_CHECK))))
|
available_free_memory(sbi, BASE_CHECK))))
|
||||||
goto redirty_out;
|
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 */
|
/* we should bypass data pages to proceed the kworkder jobs */
|
||||||
if (unlikely(f2fs_cp_error(sbi))) {
|
if (unlikely(f2fs_cp_error(sbi))) {
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
goto out;
|
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)
|
if (!wbc->for_reclaim)
|
||||||
need_balance_fs = true;
|
need_balance_fs = true;
|
||||||
else if (has_not_enough_free_secs(sbi, 0))
|
else if (has_not_enough_free_secs(sbi, 0))
|
||||||
@ -1294,16 +1292,8 @@ out:
|
|||||||
|
|
||||||
redirty_out:
|
redirty_out:
|
||||||
redirty_page_for_writepage(wbc, page);
|
redirty_page_for_writepage(wbc, page);
|
||||||
return AOP_WRITEPAGE_ACTIVATE;
|
unlock_page(page);
|
||||||
}
|
return err;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1312,8 +1302,7 @@ static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
|
|||||||
* warm/hot data page.
|
* warm/hot data page.
|
||||||
*/
|
*/
|
||||||
static int f2fs_write_cache_pages(struct address_space *mapping,
|
static int f2fs_write_cache_pages(struct address_space *mapping,
|
||||||
struct writeback_control *wbc, writepage_t writepage,
|
struct writeback_control *wbc)
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
@ -1395,16 +1384,11 @@ continue_unlock:
|
|||||||
if (!clear_page_dirty_for_io(page))
|
if (!clear_page_dirty_for_io(page))
|
||||||
goto continue_unlock;
|
goto continue_unlock;
|
||||||
|
|
||||||
ret = (*writepage)(page, wbc, data);
|
ret = mapping->a_ops->writepage(page, wbc);
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret)) {
|
||||||
if (ret == AOP_WRITEPAGE_ACTIVATE) {
|
done_index = page->index + 1;
|
||||||
unlock_page(page);
|
done = 1;
|
||||||
ret = 0;
|
break;
|
||||||
} else {
|
|
||||||
done_index = page->index + 1;
|
|
||||||
done = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (--wbc->nr_to_write <= 0 &&
|
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);
|
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
|
* if some pages were truncated, we cannot guarantee its mapping->host
|
||||||
* to detect pending bios.
|
* to detect pending bios.
|
||||||
|
Loading…
Reference in New Issue
Block a user