HULK inclusion category: bugfix bugzilla: 190156
--------------------------------
When the file is closed and the ->flush is executed, the writeback error is not consumed. As a result, when the file is written next time, the writeback error still exists, causing a new write failure.
Another problem is that in the write process, only special writeback error codes such as -EDQUOT, -EFBIG, and -ENOSPC are detected, and the error codes are consumed. In this case, other error codes may be left.
The writeback error code should be consumed unconditionally in the write(), fsync(), and close() to avoid sampling residual expired codes that are left over from the last invoking.
In the fsync process, the error code can be consumed. Therefore, this patch ensures that write and flush can consume error codes.
Fixes: 6fbda89b257f ("NFS: Replace custom error reporting mechanism with generic one") Signed-off-by: Wang Zhaolong wangzhaolong1@huawei.com --- fs/nfs/file.c | 12 ++++-------- fs/nfs/nfs4file.c | 4 +--- 2 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 35198bf6e8a5..83fec4c204b1 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -140,7 +140,6 @@ static int nfs_file_flush(struct file *file, fl_owner_t id) { struct inode *inode = file_inode(file); - errseq_t since;
dprintk("NFS: flush(%pD2)\n", file);
@@ -149,9 +148,8 @@ nfs_file_flush(struct file *file, fl_owner_t id) return 0;
/* Flush writes to the server and return any errors */ - since = filemap_sample_wb_err(file->f_mapping); nfs_wb_all(inode); - return filemap_check_wb_err(file->f_mapping, since); + return file_check_and_advance_wb_err(file); }
ssize_t @@ -603,7 +601,6 @@ 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); @@ -629,7 +626,6 @@ 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) { @@ -650,7 +646,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) return result; out: /* Return error values */ - error = filemap_check_wb_err(file->f_mapping, since); + error = file_check_and_advance_wb_err(file); switch (error) { default: break; @@ -659,9 +655,9 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) case -ENOSPC: nfs_wb_all(inode); error = file_check_and_advance_wb_err(file); - if (error < 0) - result = error; } + if (error < 0) + result = error; return result;
out_swapfile: diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 70cd0d764c44..32784a435750 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -113,7 +113,6 @@ static int nfs4_file_flush(struct file *file, fl_owner_t id) { struct inode *inode = file_inode(file); - errseq_t since;
dprintk("NFS: flush(%pD2)\n", file);
@@ -129,9 +128,8 @@ nfs4_file_flush(struct file *file, fl_owner_t id) return filemap_fdatawrite(file->f_mapping);
/* Flush writes to the server and return any errors */ - since = filemap_sample_wb_err(file->f_mapping); nfs_wb_all(inode); - return filemap_check_wb_err(file->f_mapping, since); + return file_check_and_advance_wb_err(file); }
#ifdef CONFIG_NFS_V4_2