diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 54de3e0906dcfca7f6a1d447f748a3b50bb6a213..43a2cf278548e2b4cd081ace0b499996b7eb65c7 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -148,7 +148,8 @@ nfs_file_flush(struct file *file, fl_owner_t id) return 0; /* Flush writes to the server and return any errors */ - return nfs_wb_all(inode); + nfs_wb_all(inode); + return file_check_and_advance_wb_err(file); } ssize_t @@ -585,22 +586,13 @@ 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) -{ - struct nfs_open_context *ctx; - - ctx = nfs_file_open_context(filp); - if (nfs_ctx_key_to_expire(ctx, inode)) - return 1; - return 0; -} - ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); unsigned long written = 0; ssize_t result; + int error; result = nfs_key_timeout_notify(file, inode); if (result) @@ -620,7 +612,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) if (iocb->ki_flags & IOCB_APPEND) { result = nfs_revalidate_file_size(inode, file); if (result) - goto out; + return result; } if (iocb->ki_pos > i_size_read(inode)) nfs_revalidate_mapping(inode, file->f_mapping); @@ -638,18 +630,25 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) written = result; iocb->ki_pos += written; + nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); + result = generic_write_sync(iocb, written); if (result < 0) - goto out; - + return result; +out: /* Return error values */ - if (nfs_need_check_write(file, inode)) { - int err = nfs_wb_all(inode); - if (err < 0) - result = err; + error = file_check_and_advance_wb_err(file); + switch (error) { + default: + break; + case -EDQUOT: + case -EFBIG: + case -ENOSPC: + nfs_wb_all(inode); + error = file_check_and_advance_wb_err(file); } - nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); -out: + if (error < 0) + result = error; return result; out_swapfile: diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index fc95b2a0ef9f3394cca008791733c9f6d3f2f8cb..32784a4357507c145beedb96be502c400dde5364 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -128,7 +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 */ - return nfs_wb_all(inode); + nfs_wb_all(inode); + return file_check_and_advance_wb_err(file); } #ifdef CONFIG_NFS_V4_2 diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 95d841827e2a67815c83b550fea576a10749bd64..4eca7085f52001e9a36e9076f11ee020d867426f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -310,7 +310,10 @@ static void nfs_mapping_set_error(struct page *page, int error) struct address_space *mapping = page_file_mapping(page); SetPageError(page); - mapping_set_error(mapping, error); + filemap_set_wb_err(mapping, error); + if (mapping->host) + errseq_set(&mapping->host->i_sb->s_wb_err, + error == -ENOSPC ? -ENOSPC : -EIO); nfs_set_pageerror(mapping); }