NFS: various changes relating to reporting IO errors.
authorNeilBrown <neilb@suse.com>
Mon, 11 Sep 2017 03:15:50 +0000 (13:15 +1000)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 12 Sep 2017 02:28:56 +0000 (22:28 -0400)
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: NeilBrown <neilb@suse.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/file.c
fs/nfs/internal.h
fs/nfs/pagelist.c
fs/nfs/write.c

index a385d1c3f1465a619ad71adea85a01ac4c1ecd13..0214dd1e10602b4b79f7c5c136ea0ad2bc4b832b 100644 (file)
@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
  * fall back to doing a synchronous write.
  */
 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 inode *inode = file_inode(file);
-       int have_error, do_resend, status;
+       int do_resend, status;
        int ret = 0;
 
        dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
 
        nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
        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);
-       have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
-       if (have_error) {
+       if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
                ret = xchg(&ctx->error, 0);
                if (ret)
                        goto out;
@@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        trace_nfs_fsync_enter(inode);
 
        do {
+               struct nfs_open_context *ctx = nfs_file_open_context(file);
                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)
                        break;
-               ret = nfs_file_fsync_commit(file, start, end, datasync);
+               ret = nfs_file_fsync_commit(file, datasync);
                if (!ret)
                        ret = pnfs_sync_inode(inode, !!datasync);
                /*
index 68cc22083639bb8c90ec8829a713c27a55eef75f..5bdf952f414b54c04987e1c3ce5c23ac0bf95961 100644 (file)
@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err)
                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);
+}
index bec120ec1967c4f649543852f87b5c3c3e02d8fb..d0543e19098a3327197dfbfead1a589c7e05cdba 100644 (file)
@@ -1170,8 +1170,8 @@ out_failed:
 
                /* remember fatal errors */
                if (nfs_error_is_fatal(desc->pg_error))
-                       mapping_set_error(desc->pg_inode->i_mapping,
-                                         desc->pg_error);
+                       nfs_context_set_write_error(req->wb_context,
+                                                   desc->pg_error);
 
                func = desc->pg_completion_ops->error_cleanup;
                for (midx = 0; midx < desc->pg_mirror_count; midx++) {
index c66206ac4ebf335708d5ec6c70ed0cf7fd642974..babebbccae2a0e11f12cf722a1b8dccdea75a6b8 100644 (file)
@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
                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 *
 nfs_page_private_request(struct page *page)
 {