X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4a2492630c73add3c3aa8a805ba4ff343d4a58ea..5eebf7385fedb1517b66b53c28e5aa6bb0a2be50:/bsd/nfs/nfs_socket.c diff --git a/bsd/nfs/nfs_socket.c b/bsd/nfs/nfs_socket.c index 3e9aac142..ff2f55066 100644 --- a/bsd/nfs/nfs_socket.c +++ b/bsd/nfs/nfs_socket.c @@ -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); + } } +