| From d26be718ee5f18739c98b8ffa4c932b943a916a9 Mon Sep 17 00:00:00 2001 |
| From: Scott Mayhew <smayhew@redhat.com> |
| Date: Sat, 1 Aug 2020 07:10:39 -0400 |
| Subject: [PATCH] nfs: nfs_file_write() should check for writeback errors |
| |
| commit ce368536dd614452407dc31e2449eb84681a06af upstream. |
| |
| The NFS_CONTEXT_ERROR_WRITE flag (as well as the check of said flag) was |
| removed by commit 6fbda89b257f. The absence of an error check allows |
| writes to be continually queued up for a server that may no longer be |
| able to handle them. Fix it by adding an error check using the generic |
| error reporting functions. |
| |
| Fixes: 6fbda89b257f ("NFS: Replace custom error reporting mechanism with generic one") |
| Signed-off-by: Scott Mayhew <smayhew@redhat.com> |
| Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/nfs/file.c b/fs/nfs/file.c |
| index 348f67c8f322..387a2cfa7e17 100644 |
| --- a/fs/nfs/file.c |
| +++ b/fs/nfs/file.c |
| @@ -583,12 +583,14 @@ static const struct vm_operations_struct nfs_file_vm_ops = { |
| .page_mkwrite = nfs_vm_page_mkwrite, |
| }; |
| |
| -static int nfs_need_check_write(struct file *filp, struct inode *inode) |
| +static int nfs_need_check_write(struct file *filp, struct inode *inode, |
| + int error) |
| { |
| struct nfs_open_context *ctx; |
| |
| ctx = nfs_file_open_context(filp); |
| - if (nfs_ctx_key_to_expire(ctx, inode)) |
| + if (nfs_error_is_fatal_on_server(error) || |
| + nfs_ctx_key_to_expire(ctx, inode)) |
| return 1; |
| return 0; |
| } |
| @@ -599,6 +601,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) |
| struct inode *inode = file_inode(file); |
| unsigned long written = 0; |
| ssize_t result; |
| + errseq_t since; |
| + int error; |
| |
| result = nfs_key_timeout_notify(file, inode); |
| if (result) |
| @@ -623,6 +627,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) |
| if (iocb->ki_pos > i_size_read(inode)) |
| nfs_revalidate_mapping(inode, file->f_mapping); |
| |
| + since = filemap_sample_wb_err(file->f_mapping); |
| nfs_start_io_write(inode); |
| result = generic_write_checks(iocb, from); |
| if (result > 0) { |
| @@ -641,7 +646,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) |
| goto out; |
| |
| /* Return error values */ |
| - if (nfs_need_check_write(file, inode)) { |
| + error = filemap_check_wb_err(file->f_mapping, since); |
| + if (nfs_need_check_write(file, inode, error)) { |
| int err = nfs_wb_all(inode); |
| if (err < 0) |
| result = err; |
| -- |
| 2.27.0 |
| |