Skip to content

Commit c6fd351

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFS: Further fixes to the writeback error handling
When we handle an error by redirtying the page, we're not corrupting the mapping, so we don't want the error to be recorded in the mapping. If the caller has specified a sync_mode of WB_SYNC_NONE, we can just return AOP_WRITEPAGE_ACTIVATE. However if we're dealing with WB_SYNC_ALL, we need to ensure that retries happen when the errors are non-fatal. Reported-by: Olga Kornievskaia <[email protected]> Fixes: 8fc75be ("NFS: Fix up return value on fatal errors in nfs_page_async_flush()") Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 3764a17 commit c6fd351

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

fs/nfs/write.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,9 @@ static void nfs_write_error(struct nfs_page *req, int error)
603603
* Find an associated nfs write request, and prepare to flush it out
604604
* May return an error if the user signalled nfs_wait_on_request().
605605
*/
606-
static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
607-
struct page *page)
606+
static int nfs_page_async_flush(struct page *page,
607+
struct writeback_control *wbc,
608+
struct nfs_pageio_descriptor *pgio)
608609
{
609610
struct nfs_page *req;
610611
int ret = 0;
@@ -630,11 +631,11 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
630631
/*
631632
* Remove the problematic req upon fatal errors on the server
632633
*/
633-
if (nfs_error_is_fatal(ret)) {
634-
if (nfs_error_is_fatal_on_server(ret))
635-
goto out_launder;
636-
} else
637-
ret = -EAGAIN;
634+
if (nfs_error_is_fatal_on_server(ret))
635+
goto out_launder;
636+
if (wbc->sync_mode == WB_SYNC_NONE)
637+
ret = AOP_WRITEPAGE_ACTIVATE;
638+
redirty_page_for_writepage(wbc, page);
638639
nfs_redirty_request(req);
639640
pgio->pg_error = 0;
640641
} else
@@ -650,15 +651,8 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
650651
static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
651652
struct nfs_pageio_descriptor *pgio)
652653
{
653-
int ret;
654-
655654
nfs_pageio_cond_complete(pgio, page_index(page));
656-
ret = nfs_page_async_flush(pgio, page);
657-
if (ret == -EAGAIN) {
658-
redirty_page_for_writepage(wbc, page);
659-
ret = AOP_WRITEPAGE_ACTIVATE;
660-
}
661-
return ret;
655+
return nfs_page_async_flush(page, wbc, pgio);
662656
}
663657

664658
/*
@@ -733,12 +727,15 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
733727
priority = wb_priority(wbc);
734728
}
735729

736-
nfs_pageio_init_write(&pgio, inode, priority, false,
737-
&nfs_async_write_completion_ops);
738-
pgio.pg_io_completion = ioc;
739-
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
740-
pgio.pg_error = 0;
741-
nfs_pageio_complete(&pgio);
730+
do {
731+
nfs_pageio_init_write(&pgio, inode, priority, false,
732+
&nfs_async_write_completion_ops);
733+
pgio.pg_io_completion = ioc;
734+
err = write_cache_pages(mapping, wbc, nfs_writepages_callback,
735+
&pgio);
736+
pgio.pg_error = 0;
737+
nfs_pageio_complete(&pgio);
738+
} while (err < 0 && !nfs_error_is_fatal(err));
742739
nfs_io_completion_put(ioc);
743740

744741
if (err < 0)

0 commit comments

Comments
 (0)