filemap_sample_wb_err() will return 0 if old wb error have not been consumed, then filemap_check_wb_err() will return the unchanged old wb error. Reproducer: nfs server | nfs client -----------------------------|--------------------------------------------- # No space left on server | fallocate -l 100G /svr/nospc | | mount -t nfs $nfs_server_ip:/ /mnt | | # Expected error: No space left on device | dd if=/dev/zero of=/mnt/file count=1 ibs=10K | | # Release space on mountpoint | rm /mnt/nospc | | # Unexpected error: No space left on device | dd if=/dev/zero of=/mnt/file count=1 ibs=10K Fix this by detecting writeback error from return value of nfs_wb_all(), and return the more nuanced error -(file->f_mapping->wb_err & MAX_ERRNO) if there is new wb error while nfs_wb_all(). Fixes: 67dd23f9e6fb ("nfs: ensure correct writeback errors are returned on close()") Signed-off-by: ChenXiaoSong <chenxiaosong2@xxxxxxxxxx> --- fs/nfs/file.c | 8 ++++---- fs/nfs/nfs4file.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5513ab63c108..353f1f832519 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -136,7 +136,7 @@ static int nfs_file_flush(struct file *file, fl_owner_t id) { struct inode *inode = file_inode(file); - errseq_t since; + errseq_t error = 0; dprintk("NFS: flush(%pD2)\n", file); @@ -145,9 +145,9 @@ 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); + if (nfs_wb_all(inode)) + error = filemap_check_wb_err(file->f_mapping, 0); + return error; } ssize_t diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index d258933cf8c8..cbbe66b54417 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -111,7 +111,7 @@ static int nfs4_file_flush(struct file *file, fl_owner_t id) { struct inode *inode = file_inode(file); - errseq_t since; + errseq_t error = 0; dprintk("NFS: flush(%pD2)\n", file); @@ -127,9 +127,9 @@ 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); + if (nfs_wb_all(inode)) + error = filemap_check_wb_err(file->f_mapping, 0); + return error; } #ifdef CONFIG_NFS_V4_2 -- 2.31.1