diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2021-11-09 13:57:17 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-05-09 09:14:38 +0200 |
commit | e4ea3286b1aa136e478779a791260a8f8d9e77f4 (patch) | |
tree | 4ff38fb8ada5b5469124b2658fb5eaba234d837f /fs/gfs2 | |
parent | a83ee2d81b34a5c2c4acdc9e5ea05ef6d6f3b5d6 (diff) | |
download | linux-stable-e4ea3286b1aa136e478779a791260a8f8d9e77f4.tar.gz linux-stable-e4ea3286b1aa136e478779a791260a8f8d9e77f4.tar.bz2 linux-stable-e4ea3286b1aa136e478779a791260a8f8d9e77f4.zip |
gfs2: Prevent endless loops in gfs2_file_buffered_write
[ Upstream commit 554c577cee95bdc1d03d9f457e57dc96eb791845 ]
Currently, instead of performing a short write,
iomap_file_buffered_write will fail when part of its iov iterator cannot
be read. In contrast, gfs2_file_buffered_write will loop around if it
can read part of the iov iterator, so we can end up in an endless loop.
This should be fixed in iomap_file_buffered_write (and also
generic_perform_write), but this comes a bit late in the 5.16
development cycle, so work around it in the filesystem by
trimming the iov iterator to the known-good size for now.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/file.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 247b8d95b5ef..97e2793e22d7 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -1021,6 +1021,7 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_holder *statfs_gh = NULL; size_t prev_count = 0, window_size = 0; + size_t orig_count = iov_iter_count(from); size_t read = 0; ssize_t ret; @@ -1065,6 +1066,7 @@ retry_under_glock: if (inode == sdp->sd_rindex) gfs2_glock_dq_uninit(statfs_gh); + from->count = orig_count - read; if (should_fault_in_pages(ret, from, &prev_count, &window_size)) { size_t leftover; @@ -1072,6 +1074,7 @@ retry_under_glock: leftover = fault_in_iov_iter_readable(from, window_size); gfs2_holder_disallow_demote(gh); if (leftover != window_size) { + from->count = min(from->count, window_size - leftover); if (!gfs2_holder_queued(gh)) { if (read) goto out_uninit; |