diff options
author | Peng Tao <tao.peng@primarydata.com> | 2015-12-05 10:57:31 +0300 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 22:32:37 +0300 |
commit | 0bcbf039f6b2bcefe4f5dada76079080edf9ecd0 (patch) | |
tree | 8edf8f581dcd12258d7ab84898261a3a3d0ab2ef /fs/nfs/write.c | |
parent | 2bff2288579f1e4af2f05a7f7443c85b7766d5ac (diff) | |
download | linux-0bcbf039f6b2bcefe4f5dada76079080edf9ecd0.tar.xz |
nfs: handle request add failure properly
When we fail to queue a read page to IO descriptor,
we need to clean it up otherwise it is hanging around
preventing nfs module from being removed.
When we fail to queue a write page to IO descriptor,
we need to clean it up and also save the failure status
to open context. Then at file close, we can try to write
pages back again and drop the page if it fails to writeback
in .launder_page, which will be done in the next patch.
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 7b9316406930..9dafb08ddae5 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -545,6 +545,15 @@ try_again: return head; } +static void nfs_write_error_remove_page(struct nfs_page *req) +{ + nfs_unlock_request(req); + nfs_end_page_writeback(req); + nfs_release_request(req); + generic_error_remove_page(page_file_mapping(req->wb_page), + req->wb_page); +} + /* * Find an associated nfs write request, and prepare to flush it out * May return an error if the user signalled nfs_wait_on_request(). @@ -567,8 +576,19 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, ret = 0; if (!nfs_pageio_add_request(pgio, req)) { - nfs_redirty_request(req); ret = pgio->pg_error; + /* + * Remove the problematic req upon fatal errors, + * while other dirty pages can still be around + * until they get flushed. + */ + if (nfs_error_is_fatal(ret)) { + nfs_context_set_write_error(req->wb_context, ret); + nfs_write_error_remove_page(req); + } else { + nfs_redirty_request(req); + ret = -EAGAIN; + } } else nfs_add_stats(page_file_mapping(page)->host, NFSIOS_WRITEPAGES, 1); |