|
|
| version 1.13, 2004/03/05 16:57:16 | version 1.14, 2004/03/13 03:13:53 |
|---|---|
| Line 63 | Line 63 |
| #include <netinet/in.h> | #include <netinet/in.h> |
| #include <netinet/tcp.h> | #include <netinet/tcp.h> |
| #include <sys/thread2.h> | |
| #include "rpcv2.h" | #include "rpcv2.h" |
| #include "nfsproto.h" | #include "nfsproto.h" |
| Line 871 nfsmout: | Line 872 nfsmout: |
| if (nmp->nm_cwnd > NFS_MAXCWND) | if (nmp->nm_cwnd > NFS_MAXCWND) |
| nmp->nm_cwnd = NFS_MAXCWND; | nmp->nm_cwnd = NFS_MAXCWND; |
| } | } |
| crit_enter(); /* nfs_timer interlock*/ | |
| if (rep->r_flags & R_SENT) { | if (rep->r_flags & R_SENT) { |
| rep->r_flags &= ~R_SENT; | rep->r_flags &= ~R_SENT; |
| nmp->nm_sent -= NFS_CWNDSCALE; | nmp->nm_sent -= NFS_CWNDSCALE; |
| } | } |
| crit_exit(); | |
| /* | /* |
| * Update rtt using a gain of 0.125 on the mean | * Update rtt using a gain of 0.125 on the mean |
| * and a gain of 0.25 on the deviation. | * and a gain of 0.25 on the deviation. |
| Line 1027 tryagain: | Line 1030 tryagain: |
| rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */ | rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */ |
| rep->r_rtt = rep->r_rexmit = 0; | rep->r_rtt = rep->r_rexmit = 0; |
| if (proct[procnum] > 0) | if (proct[procnum] > 0) |
| rep->r_flags = R_TIMING; | rep->r_flags = R_TIMING | R_MASKTIMER; |
| else | else |
| rep->r_flags = 0; | rep->r_flags = R_MASKTIMER; |
| rep->r_mrep = NULL; | rep->r_mrep = NULL; |
| /* | /* |
| * Do the client side RPC. | * Do the client side RPC. |
| */ | */ |
| nfsstats.rpcrequests++; | nfsstats.rpcrequests++; |
| /* | /* |
| * Chain request into list of outstanding requests. Be sure | * Chain request into list of outstanding requests. Be sure |
| * to put it LAST so timer finds oldest requests first. | * to put it LAST so timer finds oldest requests first. Note |
| * that R_MASKTIMER is set at the moment to prevent any timer | |
| * action on this request while we are still doing processing on | |
| * it below. splsoftclock() primarily protects nm_sent. Note | |
| * that we may block in this code so there is no atomicy guarentee. | |
| */ | */ |
| s = splsoftclock(); | s = splsoftclock(); |
| TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain); | TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain); |
| Line 1054 tryagain: | Line 1062 tryagain: |
| if (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM || | if (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM || |
| (nmp->nm_flag & NFSMNT_DUMBTIMR) || | (nmp->nm_flag & NFSMNT_DUMBTIMR) || |
| nmp->nm_sent < nmp->nm_cwnd)) { | nmp->nm_sent < nmp->nm_cwnd)) { |
| splx(s); | |
| if (nmp->nm_soflags & PR_CONNREQUIRED) | if (nmp->nm_soflags & PR_CONNREQUIRED) |
| error = nfs_sndlock(rep); | error = nfs_sndlock(rep); |
| if (!error) { | if (!error) { |
| Line 1068 tryagain: | Line 1075 tryagain: |
| rep->r_flags |= R_SENT; | rep->r_flags |= R_SENT; |
| } | } |
| } else { | } else { |
| splx(s); | |
| rep->r_rtt = -1; | rep->r_rtt = -1; |
| } | } |
| /* | /* |
| * Wait for the reply from our send or the timer's. | * Let the timer do what it will with the request, then |
| * wait for the reply from our send or the timer's. | |
| */ | */ |
| rep->r_flags &= ~R_MASKTIMER; | |
| splx(s); | |
| if (!error || error == EPIPE) | if (!error || error == EPIPE) |
| error = nfs_reply(rep); | error = nfs_reply(rep); |
| Line 1083 tryagain: | Line 1092 tryagain: |
| */ | */ |
| s = splsoftclock(); | s = splsoftclock(); |
| TAILQ_REMOVE(&nfs_reqq, rep, r_chain); | TAILQ_REMOVE(&nfs_reqq, rep, r_chain); |
| splx(s); | |
| /* | /* |
| * Decrement the outstanding request count. | * Decrement the outstanding request count. |
| */ | */ |
| if (rep->r_flags & R_SENT) { | if (rep->r_flags & R_SENT) { |
| rep->r_flags &= ~R_SENT; /* paranoia */ | rep->r_flags &= ~R_SENT; |
| nmp->nm_sent -= NFS_CWNDSCALE; | nmp->nm_sent -= NFS_CWNDSCALE; |
| } | } |
| splx(s); | |
| /* | /* |
| * If there was a successful reply and a tprintf msg. | * If there was a successful reply and a tprintf msg. |
| Line 1397 nfs_timer(arg) | Line 1406 nfs_timer(arg) |
| s = splnet(); | s = splnet(); |
| for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) { | for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) { |
| nmp = rep->r_nmp; | nmp = rep->r_nmp; |
| if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) | if (rep->r_mrep || (rep->r_flags & (R_SOFTTERM|R_MASKTIMER))) |
| continue; | continue; |
| if (nfs_sigintr(nmp, rep, rep->r_td)) { | if (nfs_sigintr(nmp, rep, rep->r_td)) { |
| nfs_softterm(rep); | nfs_softterm(rep); |
| Line 1515 nfs_nmcancelreqs(nmp) | Line 1524 nfs_nmcancelreqs(nmp) |
| struct nfsmount *nmp; | struct nfsmount *nmp; |
| { | { |
| struct nfsreq *req; | struct nfsreq *req; |
| int i, s; | int i, s1, s2; |
| s = splnet(); | s1 = splnet(); |
| s2 = splsoftclock(); | |
| TAILQ_FOREACH(req, &nfs_reqq, r_chain) { | TAILQ_FOREACH(req, &nfs_reqq, r_chain) { |
| if (nmp != req->r_nmp || req->r_mrep != NULL || | if (nmp != req->r_nmp || req->r_mrep != NULL || |
| (req->r_flags & R_SOFTTERM)) | (req->r_flags & R_SOFTTERM)) |
| continue; | continue; |
| nfs_softterm(req); | nfs_softterm(req); |
| } | } |
| splx(s); | splx(s2); |
| splx(s1); | |
| for (i = 0; i < 30; i++) { | for (i = 0; i < 30; i++) { |
| s = splnet(); | int s = splnet(); |
| TAILQ_FOREACH(req, &nfs_reqq, r_chain) { | TAILQ_FOREACH(req, &nfs_reqq, r_chain) { |
| if (nmp == req->r_nmp) | if (nmp == req->r_nmp) |
| break; | break; |
| Line 1544 nfs_nmcancelreqs(nmp) | Line 1555 nfs_nmcancelreqs(nmp) |
| * Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT). | * Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT). |
| * The nm_send count is decremented now to avoid deadlocks when the process in | * The nm_send count is decremented now to avoid deadlocks when the process in |
| * soreceive() hasn't yet managed to send its own request. | * soreceive() hasn't yet managed to send its own request. |
| * | |
| * This routine must be called at splsoftclock() to protect r_flags and | |
| * nm_sent. | |
| */ | */ |
| static void | static void |
| Line 1605 nfs_sndlock(struct nfsreq *rep) | Line 1619 nfs_sndlock(struct nfsreq *rep) |
| if (rep->r_nmp->nm_flag & NFSMNT_INT) | if (rep->r_nmp->nm_flag & NFSMNT_INT) |
| slpflag = PCATCH; | slpflag = PCATCH; |
| while (*statep & NFSSTA_SNDLOCK) { | while (*statep & NFSSTA_SNDLOCK) { |
| *statep |= NFSSTA_WANTSND; | |
| if (nfs_sigintr(rep->r_nmp, rep, td)) | if (nfs_sigintr(rep->r_nmp, rep, td)) |
| return (EINTR); | return (EINTR); |
| *statep |= NFSSTA_WANTSND; | |
| (void) tsleep((caddr_t)statep, slpflag, | (void) tsleep((caddr_t)statep, slpflag, |
| "nfsndlck", slptimeo); | "nfsndlck", slptimeo); |
| if (slpflag == PCATCH) { | if (slpflag == PCATCH) { |
| Line 1647 nfs_rcvlock(rep) | Line 1661 nfs_rcvlock(rep) |
| int *statep = &rep->r_nmp->nm_state; | int *statep = &rep->r_nmp->nm_state; |
| int slpflag, slptimeo = 0; | int slpflag, slptimeo = 0; |
| /* | |
| * Unconditionally check for completion in case another nfsiod | |
| * get the packet while the caller was blocked, before the caller | |
| * called us. Packet reception is handled by mainline code which | |
| * is protected by the BGL at the moment. | |
| */ | |
| if (rep->r_mrep != NULL) | |
| return (EALREADY); | |
| if (rep->r_nmp->nm_flag & NFSMNT_INT) | if (rep->r_nmp->nm_flag & NFSMNT_INT) |
| slpflag = PCATCH; | slpflag = PCATCH; |
| else | else |