]> git.baikalelectronics.ru Git - kernel.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:50:28 +0000 (08:50 +0100)
[ Upstream commit 5cfe6e5a040be6210c515bc2001c3bff5ebfd720 ]

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: 025a3b57f381 ("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 24577d1b990790505d41bcf129deb6d9f48680d4..9ee32e06f877eab0d646cd9f051ec939709d581f 100644 (file)
@@ -787,6 +787,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;
 
@@ -795,7 +796,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;