summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2017-09-10 23:15:50 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-09-11 22:28:56 -0400
commitbf4b49059718b2217339eb15c60f8753d5b0da99 (patch)
tree2093c477762d126516f215e2d7241164f098d38d
parent8224b2734ab1da4996b851e1e5d3047e7a0df499 (diff)
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: NeilBrown <neilb@suse.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/file.c16
-rw-r--r--fs/nfs/internal.h7
-rw-r--r--fs/nfs/pagelist.c4
-rw-r--r--fs/nfs/write.c7
4 files changed, 19 insertions, 15 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index a385d1c3f146..0214dd1e1060 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
208 * fall back to doing a synchronous write. 208 * fall back to doing a synchronous write.
209 */ 209 */
210static int 210static int
211nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) 211nfs_file_fsync_commit(struct file *file, int datasync)
212{ 212{
213 struct nfs_open_context *ctx = nfs_file_open_context(file); 213 struct nfs_open_context *ctx = nfs_file_open_context(file);
214 struct inode *inode = file_inode(file); 214 struct inode *inode = file_inode(file);
215 int have_error, do_resend, status; 215 int do_resend, status;
216 int ret = 0; 216 int ret = 0;
217 217
218 dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync); 218 dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
219 219
220 nfs_inc_stats(inode, NFSIOS_VFSFSYNC); 220 nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
221 do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); 221 do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
222 have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
223 status = nfs_commit_inode(inode, FLUSH_SYNC); 222 status = nfs_commit_inode(inode, FLUSH_SYNC);
224 have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); 223 if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
225 if (have_error) {
226 ret = xchg(&ctx->error, 0); 224 ret = xchg(&ctx->error, 0);
227 if (ret) 225 if (ret)
228 goto out; 226 goto out;
@@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
247 trace_nfs_fsync_enter(inode); 245 trace_nfs_fsync_enter(inode);
248 246
249 do { 247 do {
248 struct nfs_open_context *ctx = nfs_file_open_context(file);
250 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 249 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
250 if (test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
251 int ret2 = xchg(&ctx->error, 0);
252 if (ret2)
253 ret = ret2;
254 }
251 if (ret != 0) 255 if (ret != 0)
252 break; 256 break;
253 ret = nfs_file_fsync_commit(file, start, end, datasync); 257 ret = nfs_file_fsync_commit(file, datasync);
254 if (!ret) 258 if (!ret)
255 ret = pnfs_sync_inode(inode, !!datasync); 259 ret = pnfs_sync_inode(inode, !!datasync);
256 /* 260 /*
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 68cc22083639..5bdf952f414b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err)
768 return false; 768 return false;
769 } 769 }
770} 770}
771
772static inline void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
773{
774 ctx->error = error;
775 smp_wmb();
776 set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
777}
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index bec120ec1967..d0543e19098a 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -1170,8 +1170,8 @@ out_failed:
1170 1170
1171 /* remember fatal errors */ 1171 /* remember fatal errors */
1172 if (nfs_error_is_fatal(desc->pg_error)) 1172 if (nfs_error_is_fatal(desc->pg_error))
1173 mapping_set_error(desc->pg_inode->i_mapping, 1173 nfs_context_set_write_error(req->wb_context,
1174 desc->pg_error); 1174 desc->pg_error);
1175 1175
1176 func = desc->pg_completion_ops->error_cleanup; 1176 func = desc->pg_completion_ops->error_cleanup;
1177 for (midx = 0; midx < desc->pg_mirror_count; midx++) { 1177 for (midx = 0; midx < desc->pg_mirror_count; midx++) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c66206ac4ebf..babebbccae2a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
145 kref_put(&ioc->refcount, nfs_io_completion_release); 145 kref_put(&ioc->refcount, nfs_io_completion_release);
146} 146}
147 147
148static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
149{
150 ctx->error = error;
151 smp_wmb();
152 set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
153}
154
155static struct nfs_page * 148static struct nfs_page *
156nfs_page_private_request(struct page *page) 149nfs_page_private_request(struct page *page)
157{ 150{