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);