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

Reply via email to