On Thu, Jan 11, 2024 at 07:35:23PM +0000, Miod Vallat wrote:
> > The server detects that the connection is closed. It doesn't close the
> > socket immediately and starts waiting for the client to reconnect (or
> > another client, etc). As the socket is not closed, from client's point
> > of view, the connection is still not fully closaed, so it keeps
> > waiting before reconnecting with the same source port; a kind of
> > deadlock.
> >
> > The diff below fixes this by checking for EOF before sleeping.
> >
> > OK?
>
> Yes. Unfortunately NEEDQ and DISCONN may be both set, so we still need
> to check for DISCONN here before NEEDQ.
>
> Or the whole block could become
>
> if (NEEDQ set and not DISCONN set)
> nfsrv_rcv block
> if (DISCONN set)
> nfsrv_zapsock
>
> but that's probably what the compiler will rewrite the logic into.
>
Here's a new version that I prefer. If you agree, I'd rather commit
this one:
Index: nfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_syscalls.c,v
diff -u -p -r1.119 nfs_syscalls.c
--- nfs_syscalls.c 3 Aug 2023 09:49:09 -0000 1.119
+++ nfs_syscalls.c 11 Jan 2024 19:52:54 -0000
@@ -331,14 +331,15 @@ loop:
slp = nfsd->nfsd_slp;
if (ISSET(slp->ns_flag, SLP_VALID)) {
- if (ISSET(slp->ns_flag, SLP_DISCONN)) {
- nfsrv_zapsock(slp);
- } else if (ISSET(slp->ns_flag, SLP_NEEDQ)) {
+ if ((slp->ns_flag & (SLP_DISCONN | SLP_NEEDQ)) ==
+ SLP_NEEDQ) {
CLR(slp->ns_flag, SLP_NEEDQ);
nfs_sndlock(&slp->ns_solock, NULL);
nfsrv_rcv(slp->ns_so, (caddr_t)slp, M_WAIT);
nfs_sndunlock(&slp->ns_solock);
}
+ if (ISSET(slp->ns_flag, SLP_DISCONN))
+ nfsrv_zapsock(slp);
error = nfsrv_dorec(slp, nfsd, &nd);
SET(nfsd->nfsd_flag, NFSD_REQINPROG);