]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
SUNRPC: Fix a server shutdown leak
authorBenjamin Coddington <bcodding@redhat.com>
Fri, 3 Mar 2023 21:08:32 +0000 (16:08 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Mar 2023 07:57:59 +0000 (08:57 +0100)
[ Upstream commit 9ca6705d9d609441d34f8b853e1e4a6369b3b171 ]

Fix a race where kthread_stop() may prevent the threadfn from ever getting
called.  If that happens the svc_rqst will not be cleaned up.

Fixes: ed6473ddc704 ("NFSv4: Fix callback server shutdown")
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sunrpc/svc.c

index f06622814a958a5248d8407dd60024360c9019c9..7f9807374b0fb3b3a33dcb743091f882ef510f1f 100644 (file)
@@ -786,6 +786,7 @@ svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
 static int
 svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
 {
+       struct svc_rqst *rqstp;
        struct task_struct *task;
        unsigned int state = serv->sv_nrthreads-1;
 
@@ -794,7 +795,10 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
                task = choose_victim(serv, pool, &state);
                if (task == NULL)
                        break;
-               kthread_stop(task);
+               rqstp = kthread_data(task);
+               /* Did we lose a race to svo_function threadfn? */
+               if (kthread_stop(task) == -EINTR)
+                       svc_exit_thread(rqstp);
                nrservs++;
        } while (nrservs < 0);
        return 0;