Commit b35c34ed authored by Wang Zhaolong's avatar Wang Zhaolong
Browse files

nfs: Ensure write and flush consume writeback errors

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IACBGS



--------------------------------

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: 6fbda89b ("NFS: Replace custom error reporting mechanism with generic one")
Signed-off-by: default avatarWang Zhaolong <wangzhaolong1@huawei.com>
parent f0551101
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -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;
	}
	return result;

out_swapfile:
+1 −3
Original line number Diff line number Diff line
@@ -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