Skip to content

Commit

Permalink
gfs2: Prevent endless loops in gfs2_file_buffered_write
Browse files Browse the repository at this point in the history
[ Upstream commit 554c577 ]

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>
  • Loading branch information
Andreas Gruenbacher authored and gregkh committed May 9, 2022
1 parent a83ee2d commit e4ea328
Showing 1 changed file with 3 additions and 0 deletions.
3 changes: 3 additions & 0 deletions fs/gfs2/file.c
Expand Up @@ -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;

Expand Down Expand Up @@ -1065,13 +1066,15 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
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;

gfs2_holder_allow_demote(gh);
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;
Expand Down

0 comments on commit e4ea328

Please sign in to comment.