]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfs: Fix barriering when walking subrequest list
authorDavid Howells <dhowells@redhat.com>
Thu, 2 Jul 2026 08:23:02 +0000 (09:23 +0100)
committerChristian Brauner <brauner@kernel.org>
Fri, 3 Jul 2026 09:52:41 +0000 (11:52 +0200)
Fix the barriering used when walking the subrequest list in retry as
there's a possibility of seeing a subreq that's just been added by the
application thread.

Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading")
Fixes: 288ace2f57c9 ("netfs: New writeback implementation")
Link: https://sashiko.dev/#/patchset/20260608145432.681865-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/138807.1782980582@warthog.procyon.org.uk
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
fs/netfs/read_retry.c
fs/netfs/write_retry.c

index f59a70f3a086b4607172ed2365194f23fc9451c1..2b42758e01ec946232cee01eff64bca4f3489454 100644 (file)
@@ -98,7 +98,12 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
                        goto abandon;
                }
 
-               list_for_each_continue(next, &stream->subrequests) {
+               for (;;) {
+                       /* Read pointer to subreq before reading subreq state. */
+                       next = smp_load_acquire(&next->next);
+                       if (next == &stream->subrequests)
+                               break;
+
                        subreq = list_entry(next, struct netfs_io_subrequest, rreq_link);
                        if (subreq->start + subreq->transferred != start + len ||
                            test_bit(NETFS_SREQ_BOUNDARY, &subreq->flags) ||
index 32735abfa03f063ec655caef86bb8091664f28de..058bc7a166a59f766d031fe224c642ba3ba49aca 100644 (file)
@@ -72,7 +72,12 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
                    !test_bit(NETFS_SREQ_NEED_RETRY, &from->flags))
                        return;
 
-               list_for_each_continue(next, &stream->subrequests) {
+               for (;;) {
+                       /* Read pointer to subreq before reading subreq state. */
+                       next = smp_load_acquire(&next->next);
+                       if (next == &stream->subrequests)
+                               break;
+
                        subreq = list_entry(next, struct netfs_io_subrequest, rreq_link);
                        if (subreq->start + subreq->transferred != start + len ||
                            test_bit(NETFS_SREQ_BOUNDARY, &subreq->flags) ||