Commit 6fbda89b authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFS: Replace custom error reporting mechanism with generic one

Replace the NFS custom error reporting mechanism with the generic
mapping_set_error().
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent aded8d7b
...@@ -199,13 +199,6 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap); ...@@ -199,13 +199,6 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
* Flush any dirty pages for this process, and check for write errors. * Flush any dirty pages for this process, and check for write errors.
* The return status from this call provides a reliable indication of * The return status from this call provides a reliable indication of
* whether any write errors occurred for this process. * whether any write errors occurred for this process.
*
* Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to
* disk, but it retrieves and clears ctx->error after synching, despite
* the two being set at the same time in nfs_context_set_write_error().
* This is because the former is used to notify the _next_ call to
* nfs_file_write() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write.
*/ */
static int static int
nfs_file_fsync_commit(struct file *file, int datasync) nfs_file_fsync_commit(struct file *file, int datasync)
...@@ -220,11 +213,8 @@ nfs_file_fsync_commit(struct file *file, int datasync) ...@@ -220,11 +213,8 @@ nfs_file_fsync_commit(struct file *file, int datasync)
nfs_inc_stats(inode, NFSIOS_VFSFSYNC); nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC); status = nfs_commit_inode(inode, FLUSH_SYNC);
if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) { if (status == 0)
ret = xchg(&ctx->error, 0); status = file_check_and_advance_wb_err(file);
if (ret)
goto out;
}
if (status < 0) { if (status < 0) {
ret = status; ret = status;
goto out; goto out;
...@@ -245,13 +235,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -245,13 +235,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
trace_nfs_fsync_enter(inode); trace_nfs_fsync_enter(inode);
do { do {
struct nfs_open_context *ctx = nfs_file_open_context(file); ret = file_write_and_wait_range(file, start, end);
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
if (test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
int ret2 = xchg(&ctx->error, 0);
if (ret2)
ret = ret2;
}
if (ret != 0) if (ret != 0)
break; break;
ret = nfs_file_fsync_commit(file, datasync); ret = nfs_file_fsync_commit(file, datasync);
...@@ -600,8 +584,7 @@ static int nfs_need_check_write(struct file *filp, struct inode *inode) ...@@ -600,8 +584,7 @@ static int nfs_need_check_write(struct file *filp, struct inode *inode)
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
ctx = nfs_file_open_context(filp); ctx = nfs_file_open_context(filp);
if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags) || if (nfs_ctx_key_to_expire(ctx, inode))
nfs_ctx_key_to_expire(ctx, inode))
return 1; return 1;
return 0; return 0;
} }
......
...@@ -773,9 +773,3 @@ static inline bool nfs_error_is_fatal(int err) ...@@ -773,9 +773,3 @@ static inline bool nfs_error_is_fatal(int err)
} }
} }
static inline void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
{
ctx->error = error;
smp_wmb();
set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
}
...@@ -244,6 +244,12 @@ static void nfs_set_pageerror(struct address_space *mapping) ...@@ -244,6 +244,12 @@ static void nfs_set_pageerror(struct address_space *mapping)
nfs_zap_mapping(mapping->host, mapping); nfs_zap_mapping(mapping->host, mapping);
} }
static void nfs_mapping_set_error(struct page *page, int error)
{
SetPageError(page);
mapping_set_error(page_file_mapping(page), error);
}
/* /*
* nfs_page_group_search_locked * nfs_page_group_search_locked
* @head - head request of page group * @head - head request of page group
...@@ -582,9 +588,9 @@ nfs_lock_and_join_requests(struct page *page) ...@@ -582,9 +588,9 @@ nfs_lock_and_join_requests(struct page *page)
return ERR_PTR(ret); return ERR_PTR(ret);
} }
static void nfs_write_error_remove_page(struct nfs_page *req) static void nfs_write_error(struct nfs_page *req, int error)
{ {
SetPageError(req->wb_page); nfs_mapping_set_error(req->wb_page, error);
nfs_end_page_writeback(req); nfs_end_page_writeback(req);
nfs_release_request(req); nfs_release_request(req);
} }
...@@ -608,6 +614,7 @@ nfs_error_is_fatal_on_server(int err) ...@@ -608,6 +614,7 @@ nfs_error_is_fatal_on_server(int err)
static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
struct page *page) struct page *page)
{ {
struct address_space *mapping;
struct nfs_page *req; struct nfs_page *req;
int ret = 0; int ret = 0;
...@@ -621,19 +628,19 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, ...@@ -621,19 +628,19 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
nfs_set_page_writeback(page); nfs_set_page_writeback(page);
WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags)); WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
ret = req->wb_context->error;
/* If there is a fatal error that covers this write, just exit */ /* If there is a fatal error that covers this write, just exit */
if (nfs_error_is_fatal_on_server(ret)) ret = 0;
mapping = page_file_mapping(page);
if (test_bit(AS_ENOSPC, &mapping->flags) ||
test_bit(AS_EIO, &mapping->flags))
goto out_launder; goto out_launder;
ret = 0;
if (!nfs_pageio_add_request(pgio, req)) { if (!nfs_pageio_add_request(pgio, req)) {
ret = pgio->pg_error; ret = pgio->pg_error;
/* /*
* Remove the problematic req upon fatal errors on the server * Remove the problematic req upon fatal errors on the server
*/ */
if (nfs_error_is_fatal(ret)) { if (nfs_error_is_fatal(ret)) {
nfs_context_set_write_error(req->wb_context, ret);
if (nfs_error_is_fatal_on_server(ret)) if (nfs_error_is_fatal_on_server(ret))
goto out_launder; goto out_launder;
} else } else
...@@ -645,7 +652,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, ...@@ -645,7 +652,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
out: out:
return ret; return ret;
out_launder: out_launder:
nfs_write_error_remove_page(req); nfs_write_error(req, ret);
return 0; return 0;
} }
...@@ -998,7 +1005,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) ...@@ -998,7 +1005,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
(hdr->good_bytes < bytes)) { (hdr->good_bytes < bytes)) {
nfs_set_pageerror(page_file_mapping(req->wb_page)); nfs_set_pageerror(page_file_mapping(req->wb_page));
nfs_context_set_write_error(req->wb_context, hdr->error); nfs_mapping_set_error(req->wb_page, hdr->error);
goto remove_req; goto remove_req;
} }
if (nfs_write_need_commit(hdr)) { if (nfs_write_need_commit(hdr)) {
...@@ -1422,14 +1429,10 @@ static void nfs_async_write_error(struct list_head *head, int error) ...@@ -1422,14 +1429,10 @@ static void nfs_async_write_error(struct list_head *head, int error)
while (!list_empty(head)) { while (!list_empty(head)) {
req = nfs_list_entry(head->next); req = nfs_list_entry(head->next);
nfs_list_remove_request(req); nfs_list_remove_request(req);
if (nfs_error_is_fatal(error)) { if (nfs_error_is_fatal(error))
nfs_context_set_write_error(req->wb_context, error); nfs_write_error(req, error);
if (nfs_error_is_fatal_on_server(error)) { else
nfs_write_error_remove_page(req); nfs_redirty_request(req);
continue;
}
}
nfs_redirty_request(req);
} }
} }
...@@ -1843,9 +1846,10 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) ...@@ -1843,9 +1846,10 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
req->wb_bytes, req->wb_bytes,
(long long)req_offset(req)); (long long)req_offset(req));
if (status < 0) { if (status < 0) {
nfs_context_set_write_error(req->wb_context, status); if (req->wb_page) {
if (req->wb_page) nfs_mapping_set_error(req->wb_page, status);
nfs_inode_remove_request(req); nfs_inode_remove_request(req);
}
dprintk_cont(", error = %d\n", status); dprintk_cont(", error = %d\n", status);
goto next; goto next;
} }
......
...@@ -76,7 +76,6 @@ struct nfs_open_context { ...@@ -76,7 +76,6 @@ struct nfs_open_context {
fmode_t mode; fmode_t mode;
unsigned long flags; unsigned long flags;
#define NFS_CONTEXT_ERROR_WRITE (0)
#define NFS_CONTEXT_RESEND_WRITES (1) #define NFS_CONTEXT_RESEND_WRITES (1)
#define NFS_CONTEXT_BAD (2) #define NFS_CONTEXT_BAD (2)
#define NFS_CONTEXT_UNLOCK (3) #define NFS_CONTEXT_UNLOCK (3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment