mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 00:00:00 +00:00
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: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
aded8d7b54
commit
6fbda89b25
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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 @@ release_request:
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,13 +1429,9 @@ 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);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nfs_redirty_request(req);
|
nfs_redirty_request(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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 {
|
|||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user