]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netfs: Fix missing locking around retry adding new subreqs
authorDavid Howells <dhowells@redhat.com>
Tue, 12 May 2026 12:33:39 +0000 (13:33 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 12 May 2026 12:42:29 +0000 (14:42 +0200)
Fix netfs_retry_read_subrequests() and netfs_retry_write_stream() to take
the appropriate lock when adding extra subrequests into
stream->subrequests.

Fixes: e2d46f2ec332 ("netfs: Change the read result collector to only use one work item")
Fixes: 288ace2f57c9 ("netfs: New writeback implementation")
Closes: https://sashiko.dev/#/patchset/20260425125426.3855807-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260512123404.719402-3-dhowells@redhat.com
cc: Paulo Alcantara <pc@manguebit.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/netfs/read_retry.c
fs/netfs/write_retry.c

index cca9ac43c07738c2b6069fe6e6096efb69cd9b23..5ec548b996d6528d379e76c1917f795ab1fd1b9e 100644 (file)
@@ -175,7 +175,9 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
                        list_for_each_entry_safe_from(subreq, tmp,
                                                      &stream->subrequests, rreq_link) {
                                trace_netfs_sreq(subreq, netfs_sreq_trace_superfluous);
+                               spin_lock(&rreq->lock);
                                list_del(&subreq->rreq_link);
+                               spin_unlock(&rreq->lock);
                                netfs_put_subrequest(subreq, netfs_sreq_trace_put_done);
                                if (subreq == to)
                                        break;
@@ -203,8 +205,10 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
                                             refcount_read(&subreq->ref),
                                             netfs_sreq_trace_new);
 
+                       spin_lock(&rreq->lock);
                        list_add(&subreq->rreq_link, &to->rreq_link);
-                       to = list_next_entry(to, rreq_link);
+                       spin_unlock(&rreq->lock);
+                       to = subreq;
                        trace_netfs_sreq(subreq, netfs_sreq_trace_retry);
 
                        stream->sreq_max_len    = umin(len, rreq->rsize);
index 29489a23a2209371f5db156a40f2ab5fc35d41be..32735abfa03f063ec655caef86bb8091664f28de 100644 (file)
@@ -130,7 +130,9 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
                        list_for_each_entry_safe_from(subreq, tmp,
                                                      &stream->subrequests, rreq_link) {
                                trace_netfs_sreq(subreq, netfs_sreq_trace_discard);
+                               spin_lock(&wreq->lock);
                                list_del(&subreq->rreq_link);
+                               spin_unlock(&wreq->lock);
                                netfs_put_subrequest(subreq, netfs_sreq_trace_put_done);
                                if (subreq == to)
                                        break;
@@ -153,8 +155,10 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
                                             netfs_sreq_trace_new);
                        trace_netfs_sreq(subreq, netfs_sreq_trace_split);
 
+                       spin_lock(&wreq->lock);
                        list_add(&subreq->rreq_link, &to->rreq_link);
-                       to = list_next_entry(to, rreq_link);
+                       spin_unlock(&wreq->lock);
+                       to = subreq;
                        trace_netfs_sreq(subreq, netfs_sreq_trace_retry);
 
                        stream->sreq_max_len    = len;