]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_socket.c
xnu-517.9.5.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_socket.c
index 3e9aac142c44aac96a3b65603da0b8aeb5e63a7f..ff2f55066d0e05d3edf18ec5deea59a6d6fc2d0c 100644 (file)
@@ -1,24 +1,21 @@
 /*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -181,8 +178,6 @@ int nfsrtton = 0;
 struct nfsrtt nfsrtt;
 
 static int     nfs_msg __P((struct proc *, const char *, const char *, int));
-static void    nfs_up(struct nfsreq *, const char *, int);
-static void    nfs_down(struct nfsreq *, const char *, int);
 static int     nfs_rcvlock __P((struct nfsreq *));
 static void    nfs_rcvunlock __P((struct nfsreq *));
 static int     nfs_receive __P((struct nfsreq *rep, struct mbuf **aname,
@@ -670,7 +665,8 @@ nfs_reconnect(rep)
                        return (EINTR);
                if (error == EIO)
                        return (EIO);
-               nfs_down(rep, "can not connect", error);
+               nfs_down(rep, rep->r_nmp, rep->r_procp, "can not connect",
+                       error, NFSSTA_TIMEO);
                if (!(nmp->nm_state & NFSSTA_MOUNTED)) {
                        /* we're not yet completely mounted and */
                        /* we can't reconnect, so we fail */
@@ -1001,6 +997,7 @@ tryagain:
 
                        thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
                        do {
+                           control = NULL;
                            rcvflg = 0;
                            error =  soreceive(so, (struct sockaddr **)0,
                                               &auio, mp, &control, &rcvflg);
@@ -1039,10 +1036,12 @@ errout:
                                    error,
                                 rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
                        error = nfs_sndlock(rep);
-                       if (!error)
+                       if (!error) {
                                error = nfs_reconnect(rep);
-                       if (!error)
-                               goto tryagain;
+                               if (!error)
+                                       goto tryagain;
+                               nfs_sndunlock(rep);
+                       }
                }
        } else {
                /*
@@ -1186,13 +1185,14 @@ nfs_reply(myrep)
                 * Get the next Rpc reply off the socket. Assume myrep->r_nmp
                 * is still intact by checks done in nfs_rcvlock.
                 */
+               /* XXX why do we ask for nam here? we don't use it! */
                error = nfs_receive(myrep, &nam, &mrep);
                if (nam)
                        m_freem(nam);
                /*
                 * Bailout asap if nfsmount struct gone (unmounted). 
                 */
-               if (!myrep->r_nmp || !nmp->nm_so) {
+               if (!myrep->r_nmp) {
                        FSDBG(530, myrep->r_xid, myrep, nmp, -2);
                        return (ENXIO);
                }
@@ -1201,14 +1201,15 @@ nfs_reply(myrep)
                        nfs_rcvunlock(myrep);
 
                        /* Bailout asap if nfsmount struct gone (unmounted). */
-                       if (!myrep->r_nmp || !nmp->nm_so)
+                       if (!myrep->r_nmp)
                                return (ENXIO);
 
                        /*
                         * Ignore routing errors on connectionless protocols??
                         */
                        if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) {
-                               nmp->nm_so->so_error = 0;
+                               if (nmp->nm_so)
+                                       nmp->nm_so->so_error = 0;
                                if (myrep->r_flags & R_GETONEREP)
                                        return (0);
                                continue;
@@ -1230,6 +1231,7 @@ nfs_reply(myrep)
                  * just check here and get out. (ekn)
                 */
                if (!mrep) {
+                       nfs_rcvunlock(myrep);
                         FSDBG(530, myrep->r_xid, myrep, nmp, -3);
                         return (ENXIO); /* sounds good */
                 }
@@ -1404,6 +1406,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp, xidp)
        int nmsotype;
        struct timeval now;
 
+       if (mrp)
+               *mrp = NULL;
        if (xidp)
                *xidp = 0;
 
@@ -1598,7 +1602,8 @@ tryagain:
         * If there was a successful reply and a tprintf msg.
         * tprintf a response.
         */
-       nfs_up(rep, "is alive again", error);
+       if (!error)
+               nfs_up(rep, nmp, procp, "is alive again", NFSSTA_TIMEO);
        mrep = rep->r_mrep;
        md = rep->r_md;
        dpos = rep->r_dpos;
@@ -1688,8 +1693,10 @@ tryagain:
                                *mdp = md;
                                *dposp = dpos;
                                error |= NFSERR_RETERR;
-                       } else
+                       } else {
                                m_freem(mrep);
+                               error &= ~NFSERR_RETERR;
+                       }
                        m_freem(rep->r_mreq);
                        FSDBG_BOT(531, error, rep->r_xid, nmp, rep);
                        FREE_ZONE((caddr_t)rep,
@@ -2044,7 +2051,8 @@ nfs_timer(arg)
                    (rep->r_rexmit > 2 || (rep->r_flags & R_RESENDERR)) &&
                    rep->r_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
                        rep->r_lastmsg = now.tv_sec;
-                       nfs_down(rep, "not responding", 0);
+                       nfs_down(rep, rep->r_nmp, rep->r_procp, "not responding",
+                               0, NFSSTA_TIMEO);
                        if (!(nmp->nm_state & NFSSTA_MOUNTED)) {
                                /* we're not yet completely mounted and */
                                /* we can't complete an RPC, so we fail */
@@ -2168,11 +2176,11 @@ nfs_timer(arg)
                                rep->r_rtt = 0;
                }
        }
+       microuptime(&now);
 #ifndef NFS_NOSERVER
        /*
         * Call the nqnfs server timer once a second to handle leases.
         */
-       microuptime(&now);
        if (lasttime != now.tv_sec) {
                lasttime = now.tv_sec;
                nqnfs_serverd();
@@ -2190,6 +2198,15 @@ nfs_timer(arg)
        }
 #endif /* NFS_NOSERVER */
        splx(s);
+
+       if (nfsbuffreeuptimestamp + 30 <= now.tv_sec) {
+               /*
+                * We haven't called nfs_buf_freeup() in a little while.
+                * So, see if we can free up any stale/unused bufs now.
+                */
+               nfs_buf_freeup(1);
+       }
+
        timeout(nfs_timer_funnel, (void *)0, nfs_ticks);
 
 }
@@ -3038,41 +3055,52 @@ nfs_msg(p, server, msg, error)
        return (0);
 }
 
-static void
-nfs_down(rep, msg, error)
+void
+nfs_down(rep, nmp, proc, msg, error, flags)
        struct nfsreq *rep;
+       struct nfsmount *nmp;
+       struct proc *proc;
        const char *msg;
-       int error;
+       int error, flags;
 {
-       int dosignal;
-
-       if (rep == NULL || rep->r_nmp == NULL)
+       if (nmp == NULL)
                return;
-       if (!(rep->r_nmp->nm_state & NFSSTA_TIMEO)) {
-               vfs_event_signal(&rep->r_nmp->nm_mountp->mnt_stat.f_fsid,
+       if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) {
+               vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
                    VQ_NOTRESP, 0);
-               rep->r_nmp->nm_state |= NFSSTA_TIMEO;
+               nmp->nm_state |= NFSSTA_TIMEO;
        }
-       rep->r_flags |= R_TPRINTFMSG;
-       nfs_msg(rep->r_procp, rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname,
-           msg, error);
+       if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) {
+               vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
+                   VQ_NOTRESPLOCK, 0);
+               nmp->nm_state |= NFSSTA_LOCKTIMEO;
+       }
+       if (rep)
+               rep->r_flags |= R_TPRINTFMSG;
+       nfs_msg(proc, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error);
 }
 
-static void
-nfs_up(rep, msg, error)
+void
+nfs_up(rep, nmp, proc, msg, flags)
        struct nfsreq *rep;
+       struct nfsmount *nmp;
+       struct proc *proc;
        const char *msg;
-       int error;
+       int flags;
 {
-
-       if (error != 0 || rep == NULL || rep->r_nmp == NULL)
+       if (nmp == NULL)
                return;
-       if ((rep->r_flags & R_TPRINTFMSG) != 0)
-               nfs_msg(rep->r_procp,
-                   rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
-       if ((rep->r_nmp->nm_state & NFSSTA_TIMEO)) {
-               rep->r_nmp->nm_state &= ~NFSSTA_TIMEO;
-               vfs_event_signal(&rep->r_nmp->nm_mountp->mnt_stat.f_fsid,
+       if ((rep == NULL) || (rep->r_flags & R_TPRINTFMSG) != 0)
+               nfs_msg(proc, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
+       if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) {
+               nmp->nm_state &= ~NFSSTA_TIMEO;
+               vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
                    VQ_NOTRESP, 1);
        }
+       if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
+               nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
+               vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
+                   VQ_NOTRESPLOCK, 1);
+       }
 }
+