Commit bf4b4905 authored by NeilBrown's avatar NeilBrown Committed by Trond Myklebust

NFS: various changes relating to reporting IO errors.

1/ remove 'start' and 'end' args from nfs_file_fsync_commit().
   They aren't used.

2/ Make nfs_context_set_write_error() a "static inline" in internal.h
   so we can...

3/ Use nfs_context_set_write_error() instead of mapping_set_error()
   if nfs_pageio_add_request() fails before sending any request.
   NFS generally keeps errors in the open_context, not the mapping,
   so this is more consistent.

4/ If filemap_write_and_write_range() reports any error, still
   check ctx->error.  The value in ctx->error is likely to be
   more useful.  As part of this, NFS_CONTEXT_ERROR_WRITE is
   cleared slightly earlier, before nfs_file_fsync_commit() is called,
   rather than at the start of that function.
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 8224b273
...@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap); ...@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
* fall back to doing a synchronous write. * fall back to doing a synchronous write.
*/ */
static int static int
nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) nfs_file_fsync_commit(struct file *file, int datasync)
{ {
struct nfs_open_context *ctx = nfs_file_open_context(file); struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
int have_error, do_resend, status; int do_resend, status;
int ret = 0; int ret = 0;
dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync); dprintk("NFS: fsync file(%pD2) datasync %d\n", file, 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);
have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC); status = nfs_commit_inode(inode, FLUSH_SYNC);
have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
if (have_error) {
ret = xchg(&ctx->error, 0); ret = xchg(&ctx->error, 0);
if (ret) if (ret)
goto out; goto out;
...@@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -247,10 +245,16 @@ 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 = filemap_write_and_wait_range(inode->i_mapping, 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, start, end, datasync); ret = nfs_file_fsync_commit(file, datasync);
if (!ret) if (!ret)
ret = pnfs_sync_inode(inode, !!datasync); ret = pnfs_sync_inode(inode, !!datasync);
/* /*
......
...@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err) ...@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err)
return false; return false;
} }
} }
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);
}
...@@ -1170,8 +1170,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, ...@@ -1170,8 +1170,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
/* remember fatal errors */ /* remember fatal errors */
if (nfs_error_is_fatal(desc->pg_error)) if (nfs_error_is_fatal(desc->pg_error))
mapping_set_error(desc->pg_inode->i_mapping, nfs_context_set_write_error(req->wb_context,
desc->pg_error); desc->pg_error);
func = desc->pg_completion_ops->error_cleanup; func = desc->pg_completion_ops->error_cleanup;
for (midx = 0; midx < desc->pg_mirror_count; midx++) { for (midx = 0; midx < desc->pg_mirror_count; midx++) {
......
...@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc) ...@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
kref_put(&ioc->refcount, nfs_io_completion_release); kref_put(&ioc->refcount, nfs_io_completion_release);
} }
static 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);
}
static struct nfs_page * static struct nfs_page *
nfs_page_private_request(struct page *page) nfs_page_private_request(struct page *page)
{ {
......
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