]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfs: Fix hang due to missing case in final DIO read result collection
authorDavid Howells <dhowells@redhat.com>
Tue, 1 Jul 2025 16:38:36 +0000 (17:38 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 1 Jul 2025 20:37:12 +0000 (22:37 +0200)
When doing a DIO read, if the subrequests we issue fail and cause the
request PAUSE flag to be set to put a pause on subrequest generation, we
may complete collection of the subrequests (possibly discarding them) prior
to the ALL_QUEUED flags being set.

In such a case, netfs_read_collection() doesn't see ALL_QUEUED being set
after netfs_collect_read_results() returns and will just return to the app
(the collector can be seen unpausing the generator in the trace log).

The subrequest generator can then set ALL_QUEUED and the app thread reaches
netfs_wait_for_request().  This causes netfs_collect_in_app() to be called
to see if we're done yet, but there's missing case here.

netfs_collect_in_app() will see that a thread is active and set inactive to
false, but won't see any subrequests in the read stream, and so won't set
need_collect to true.  The function will then just return 0, indicating
that the caller should just sleep until further activity (which won't be
forthcoming) occurs.

Fix this by making netfs_collect_in_app() check to see if an active thread
is complete - i.e. that ALL_QUEUED is set and the subrequests list is empty
- and to skip the sleep return path.  The collector will then be called
which will clear the request IN_PROGRESS flag, allowing the app to
progress.

Fixes: 2b1424cd131c ("netfs: Fix wait/wake to be consistent about the waitqueue used")
Reported-by: Steve French <sfrench@samba.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/20250701163852.2171681-2-dhowells@redhat.com
Tested-by: Steve French <sfrench@samba.org>
Reviewed-by: Paulo Alcantara <pc@manguebit.org>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/netfs/misc.c

index 43b67a28a8fa07b265c354b919766561d69285ad..0a54b12034868922e6b0a99ba4ee6abb5bccc2e0 100644 (file)
@@ -381,7 +381,7 @@ void netfs_wait_for_in_progress_stream(struct netfs_io_request *rreq,
 static int netfs_collect_in_app(struct netfs_io_request *rreq,
                                bool (*collector)(struct netfs_io_request *rreq))
 {
-       bool need_collect = false, inactive = true;
+       bool need_collect = false, inactive = true, done = true;
 
        for (int i = 0; i < NR_IO_STREAMS; i++) {
                struct netfs_io_subrequest *subreq;
@@ -400,9 +400,11 @@ static int netfs_collect_in_app(struct netfs_io_request *rreq,
                        need_collect = true;
                        break;
                }
+               if (subreq || !test_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags))
+                       done = false;
        }
 
-       if (!need_collect && !inactive)
+       if (!need_collect && !inactive && !done)
                return 0; /* Sleep */
 
        __set_current_state(TASK_RUNNING);