From db8c27f499105dcc9872dcc46e88bdd570c24fee Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Tue, 27 Apr 2021 15:32:35 -0700 Subject: [PATCH] nfsd: fix a NFSv4.1 Linux client mount stuck in CLOSE_WAIT It was reported that a NFSv4.1 Linux client mount against a FreeBSD12 server was hung, with the TCP connection in CLOSE_WAIT state on the server. When a NFSv4.1/4.2 mount is done and the back channel is bound to the TCP connection, the soclose() is delayed until a new TCP connection is bound to the back channel, due to a reference count being held on the SVCXPRT structure in the krpc for the socket. Without the soclose() call, the socket will remain in CLOSE_WAIT and this somehow caused the Linux client to hang. This patch adds calls to soshutdown(.., SHUT_WR) that are performed when the server side krpc sees that the socket is no longer usable. Since this can be done before the back channel is bound to a new TCP connection, it allows the TCP connection to proceed to CLOSED state. PR: 254590 Reported by: jbreitman@tildenparkcapital.com Reviewed by: tuexen Comments by: kevans MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D29526 --- sys/rpc/svc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c index a059096e7b77..be0f08ebca9d 100644 --- a/sys/rpc/svc.c +++ b/sys/rpc/svc.c @@ -203,6 +203,8 @@ svcpool_cleanup(SVCPOOL *pool) mtx_unlock(&grp->sg_lock); } TAILQ_FOREACH_SAFE(xprt, &cleanup, xp_link, nxprt) { + if (xprt->xp_socket != NULL) + soshutdown(xprt->xp_socket, SHUT_WR); SVC_RELEASE(xprt); } @@ -388,6 +390,8 @@ xprt_unregister(SVCXPRT *xprt) xprt_unregister_locked(xprt); mtx_unlock(&grp->sg_lock); + if (xprt->xp_socket != NULL) + soshutdown(xprt->xp_socket, SHUT_WR); SVC_RELEASE(xprt); } @@ -1078,6 +1082,7 @@ svc_checkidle(SVCGROUP *grp) mtx_unlock(&grp->sg_lock); TAILQ_FOREACH_SAFE(xprt, &cleanup, xp_link, nxprt) { + soshutdown(xprt->xp_socket, SHUT_WR); SVC_RELEASE(xprt); } mtx_lock(&grp->sg_lock);