Skip to content

Commit e600543

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFS: Don't report ENOSPC write errors twice
Any errors reported by the write() system call need to be cleared from the file descriptor's error tracking. The current call to nfs_wb_all() causes the error to be reported, but since it doesn't call file_check_and_advance_wb_err(), we can end up reporting the same error a second time when the application calls fsync(). Note that since Linux 4.13, the rule is that EIO may be reported for write(), but it must be reported by a subsequent fsync(), so let's just drop reporting it in write. The check for nfs_ctx_key_to_expire() is just a duplicate to the one already in nfs_write_end(), so let's drop that too. Reported-by: ChenXiaoSong <chenxiaosong2@huawei.com> Fixes: ce36853 ("nfs: nfs_file_write() should check for writeback errors") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 9641d9b commit e600543

1 file changed

Lines changed: 14 additions & 20 deletions

File tree

fs/nfs/file.c

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -598,18 +598,6 @@ static const struct vm_operations_struct nfs_file_vm_ops = {
598598
.page_mkwrite = nfs_vm_page_mkwrite,
599599
};
600600

601-
static int nfs_need_check_write(struct file *filp, struct inode *inode,
602-
int error)
603-
{
604-
struct nfs_open_context *ctx;
605-
606-
ctx = nfs_file_open_context(filp);
607-
if (nfs_error_is_fatal_on_server(error) ||
608-
nfs_ctx_key_to_expire(ctx, inode))
609-
return 1;
610-
return 0;
611-
}
612-
613601
ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
614602
{
615603
struct file *file = iocb->ki_filp;
@@ -637,7 +625,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
637625
if (iocb->ki_flags & IOCB_APPEND || iocb->ki_pos > i_size_read(inode)) {
638626
result = nfs_revalidate_file_size(inode, file);
639627
if (result)
640-
goto out;
628+
return result;
641629
}
642630

643631
nfs_clear_invalid_mapping(file->f_mapping);
@@ -656,6 +644,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
656644

657645
written = result;
658646
iocb->ki_pos += written;
647+
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
659648

660649
if (mntflags & NFS_MOUNT_WRITE_EAGER) {
661650
result = filemap_fdatawrite_range(file->f_mapping,
@@ -673,17 +662,22 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
673662
}
674663
result = generic_write_sync(iocb, written);
675664
if (result < 0)
676-
goto out;
665+
return result;
677666

667+
out:
678668
/* Return error values */
679669
error = filemap_check_wb_err(file->f_mapping, since);
680-
if (nfs_need_check_write(file, inode, error)) {
681-
int err = nfs_wb_all(inode);
682-
if (err < 0)
683-
result = err;
670+
switch (error) {
671+
default:
672+
break;
673+
case -EDQUOT:
674+
case -EFBIG:
675+
case -ENOSPC:
676+
nfs_wb_all(inode);
677+
error = file_check_and_advance_wb_err(file);
678+
if (error < 0)
679+
result = error;
684680
}
685-
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
686-
out:
687681
return result;
688682

689683
out_swapfile:

0 commit comments

Comments
 (0)