diff mbox series

[RESEND] vfs: protect file->f_sb_err with f_lock

Message ID 20201219134804.20034-1-jlayton@kernel.org (mailing list archive)
State New, archived
Headers show
Series [RESEND] vfs: protect file->f_sb_err with f_lock | expand

Commit Message

Jeff Layton Dec. 19, 2020, 1:48 p.m. UTC
When I added the ability for syncfs to report writeback errors, I
neglected to adequately protect file->f_sb_err. We could have racing
updates to that value if two tasks are issuing syncfs() on the same
fd at the same time.

Fix this by protecting the f_sb_err field with the file->f_lock,
similarly to how the f_wb_err field is protected.

Cc: stable@vger.kernel.org # v5.8+
Fixes: 735e4ae5ba28 (vfs: track per-sb writeback errors and report them to syncfs)
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/sync.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

I sent this a couple of weeks ago, but no one picked it up. No changes
from the original posting, but added the Fixes tag and marked it for
stable.
diff mbox series

Patch

diff --git a/fs/sync.c b/fs/sync.c
index 1373a610dc78..3be26ff72431 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -162,7 +162,7 @@  SYSCALL_DEFINE1(syncfs, int, fd)
 {
 	struct fd f = fdget(fd);
 	struct super_block *sb;
-	int ret, ret2;
+	int ret, ret2 = 0;
 
 	if (!f.file)
 		return -EBADF;
@@ -172,7 +172,12 @@  SYSCALL_DEFINE1(syncfs, int, fd)
 	ret = sync_filesystem(sb);
 	up_read(&sb->s_umount);
 
-	ret2 = errseq_check_and_advance(&sb->s_wb_err, &f.file->f_sb_err);
+	if (errseq_check(&sb->s_wb_err, f.file->f_sb_err)) {
+		/* Something changed, must use slow path */
+		spin_lock(&f.file->f_lock);
+		ret2 = errseq_check_and_advance(&sb->s_wb_err, &f.file->f_sb_err);
+		spin_unlock(&f.file->f_lock);
+	}
 
 	fdput(f);
 	return ret ? ret : ret2;