netfs: Advance iterator correctly rather than jumping it
authorDavid Howells <dhowells@redhat.com>
Fri, 27 Sep 2024 08:08:42 +0000 (09:08 +0100)
committerChristian Brauner <brauner@kernel.org>
Fri, 27 Sep 2024 16:29:20 +0000 (18:29 +0200)
In netfs_write_folio(), use iov_iter_advance() to advance the folio as we
split bits of it off to subrequests rather than manually jumping the
->iov_offset value around.  This becomes more problematic when we use a
bounce buffer made out of single-page folios to cover a multipage pagecache
folio.

Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/2238548.1727424522@warthog.procyon.org.uk
cc: Jeff Layton <jlayton@kernel.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/netfs/write_issue.c

index 04e66d587f777cf8fec1b46ce58cf1dc49ea28b0..f9761d11791dc6b611c28dba8c28e1f725cb63b9 100644 (file)
@@ -307,6 +307,7 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
        struct netfs_io_stream *stream;
        struct netfs_group *fgroup; /* TODO: Use this with ceph */
        struct netfs_folio *finfo;
+       size_t iter_off = 0;
        size_t fsize = folio_size(folio), flen = fsize, foff = 0;
        loff_t fpos = folio_pos(folio), i_size;
        bool to_eof = false, streamw = false;
@@ -462,7 +463,12 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
                if (choose_s < 0)
                        break;
                stream = &wreq->io_streams[choose_s];
-               wreq->io_iter.iov_offset = stream->submit_off;
+
+               /* Advance the iterator(s). */
+               if (stream->submit_off > iter_off) {
+                       iov_iter_advance(&wreq->io_iter, stream->submit_off - iter_off);
+                       iter_off = stream->submit_off;
+               }
 
                atomic64_set(&wreq->issued_to, fpos + stream->submit_off);
                stream->submit_extendable_to = fsize - stream->submit_off;
@@ -477,8 +483,8 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
                        debug = true;
        }
 
-       wreq->io_iter.iov_offset = 0;
-       iov_iter_advance(&wreq->io_iter, fsize);
+       if (fsize > iter_off)
+               iov_iter_advance(&wreq->io_iter, fsize - iter_off);
        atomic64_set(&wreq->issued_to, fpos + fsize);
 
        if (!debug)