--- kernel/bsd/nfs/nfs_socket.c 2018/04/24 18:26:01 1.1 +++ kernel/bsd/nfs/nfs_socket.c 2018/04/24 18:27:49 1.1.1.2 @@ -203,6 +203,82 @@ int (*nfsrv3_procs[NFS_NPROCS]) __P((str }; #endif /* NFS_NOSERVER */ +#if DIAGNOSTIC +uint nfstraceindx = 0; +struct nfstracerec nfstracebuf[NFSTBUFSIZ] = {{0,0,0,0}}; +uint nfstracemask = 0; /* enables trace points 0 to 31 (right to left) */ + +int nfsprnttimo = 1; + +int nfsodata[1024]; +int nfsoprocnum, nfsolen; +int nfsbt[32], nfsbtlen; + +int +backtrace(int *where, int size) +{ + int register sp, *fp, numsaved; + + __asm__ volatile("mr %0,r1" : "=r" (sp)); + + fp = (int *)*((int *)sp); + size /= sizeof(int); + for (numsaved = 0; numsaved < size; numsaved++) { + *where++ = fp[2]; + if ((int)fp <= 0) + break; + fp = (int *)*fp; + } + return (numsaved); +} + +void +nfsdup(struct nfsreq *rep) +{ + int *ip, i, first = 1, end; + char *s, b[240]; + struct mbuf *mb; + + if ((nfs_debug & NFS_DEBUG_DUP) == 0) + return; + /* last mbuf in chain will be nfs content */ + for (mb = rep->r_mreq; mb->m_next; mb = mb->m_next) + ; + if (rep->r_procnum == nfsoprocnum && mb->m_len == nfsolen && + !bcmp((caddr_t)nfsodata, mb->m_data, nfsolen)) { + s = b + sprintf(b, "nfsdup x=%x p=%d h=", rep->r_xid, + rep->r_procnum); + end = (int)(VTONFS(rep->r_vp)->n_fhp); + ip = (int *)(end & ~3); + end += VTONFS(rep->r_vp)->n_fhsize; + while ((int)ip < end) { + i = *ip++; + if (first) { /* avoid leading zeroes */ + if (i == 0) + continue; + first = 0; + s += sprintf(s, "%x", i); + } else + s += sprintf(s, "%08x", i); + } + if (first) + sprintf(s, "%x", 0); + else /* eliminate trailing zeroes */ + while (*--s == '0') + *s = 0; + /* + * set a breakpoint here and you can view the + * current backtrace and the one saved in nfsbt + */ + kprintf("%s\n", b); + } + nfsoprocnum = rep->r_procnum; + nfsolen = mb->m_len; + bcopy(mb->m_data, (caddr_t)nfsodata, mb->m_len); + nfsbtlen = backtrace(&nfsbt, sizeof(nfsbt)); +} +#endif + /* * Initialize sockets and congestion for a new NFS connection. * We do not free the sockaddr if error. @@ -326,10 +402,10 @@ nfs_connect(nmp, rep) so->so_snd.sb_flags |= SB_NOINTR; /* Initialize other non-zero congestion variables */ - nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] = nmp->nm_srtt[3] = - nmp->nm_srtt[4] = (NFS_TIMEO << 3); + nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] = + nmp->nm_srtt[3] = (NFS_TIMEO << 3); nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] = - nmp->nm_sdrtt[3] = nmp->nm_sdrtt[4] = 0; + nmp->nm_sdrtt[3] = 0; nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */ nmp->nm_sent = 0; nmp->nm_timeouts = 0; @@ -364,6 +440,7 @@ nfs_reconnect(rep) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfscon", 0); } + NFS_DPF(DUP, ("nfs_reconnect RESEND\n")); /* * Loop through outstanding request list and fix up all requests * on old socket. @@ -438,6 +515,10 @@ nfs_send(so, nam, top, rep) else flags = 0; +#if DIAGNOSTIC + if (rep) + nfsdup(rep); +#endif error = sosend(so, sendnam, (struct uio *)0, top, (struct mbuf *)0, flags); if (error) { @@ -450,8 +531,12 @@ nfs_send(so, nam, top, rep) */ if (rep->r_flags & R_SOFTTERM) error = EINTR; - else + else { rep->r_flags |= R_MUSTRESEND; + NFS_DPF(DUP, + ("nfs_send RESEND error=%d\n", + error)); + } } else log(LOG_INFO, "nfsd send error %d\n", error); @@ -535,9 +620,9 @@ tryagain: while (rep->r_flags & R_MUSTRESEND) { m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT); nfsstats.rpcretries++; -#if DIAGNOSTIC - kprintf("nfs_receive %s flg=0x%x\n", rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname, rep->r_nmp->nm_flag); -#endif + NFS_DPF(DUP, + ("nfs_receive RESEND %s\n", + rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname)); error = nfs_send(so, rep->r_nmp->nm_nam, m, rep); if (error) { if (error == EINTR || error == ERESTART || @@ -794,6 +879,8 @@ nfsmout: rt->rto = NFS_RTO(nmp, proct[rep->r_procnum]); rt->sent = nmp->nm_sent; rt->cwnd = nmp->nm_cwnd; + if (proct[rep->r_procnum] == 0) + panic("nfs_reply: proct[%d] is zero", rep->r_procnum); rt->srtt = nmp->nm_srtt[proct[rep->r_procnum] - 1]; rt->sdrtt = nmp->nm_sdrtt[proct[rep->r_procnum] - 1]; rt->fsid = nmp->nm_mountp->mnt_stat.f_fsid; @@ -831,6 +918,8 @@ nfsmout: * rtt is between N+dt and N+2-dt ticks, * add 1. */ + if (proct[rep->r_procnum] == 0) + panic("nfs_reply: proct[%d] is zero", rep->r_procnum); t1 = rep->r_rtt + 1; t1 -= (NFS_SRTT(rep) >> 3); NFS_SRTT(rep) += t1; @@ -901,6 +990,7 @@ nfs_request(vp, mrest, procnum, procp, c NFSTRACE4(NFSTRC_REQ, vp, procnum, 0, 0); nmp = VFSTONFS(vp->v_mount); + MALLOC_ZONE(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK); rep->r_nmp = nmp; @@ -1094,9 +1184,11 @@ tryagain: m_freem(mrep); error = 0; waituntil = time.tv_sec + trylater_delay; -#if DIAGNOSTIC - kprintf("nfs_request %s flag=%x trylater_cnt=%x waituntil=%lx trylater_delay=%x\n", nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_flag, trylater_cnt, waituntil, trylater_delay); -#endif + NFS_DPF(DUP, + ("nfs_request %s flag=%x trylater_cnt=%x waituntil=%lx trylater_delay=%x\n", + nmp->nm_mountp->mnt_stat.f_mntfromname, + nmp->nm_flag, trylater_cnt, waituntil, + trylater_delay)); while (time.tv_sec < waituntil) (void) tsleep((caddr_t)&lbolt, PSOCK, "nqnfstry", 0); @@ -1315,10 +1407,6 @@ nfs_rephead(siz, nd, slp, err, cache, fr #endif /* NFS_NOSERVER */ -#if DIAGNOSTIC -int nfsprnttimo = 2; -#endif - /* * Nfs timer routine * Scan the nfsreq list and retranmit any requests that have timed out @@ -1347,6 +1435,8 @@ nfs_timer(arg) s = splnet(); for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) { nmp = rep->r_nmp; + if (!nmp) /* unmounted */ + continue; if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) continue; if (nfs_sigintr(nmp, rep, rep->r_procp)) { @@ -1359,6 +1449,9 @@ nfs_timer(arg) timeo = nmp->nm_timeo; else timeo = NFS_RTO(nmp, proct[rep->r_procnum]); + /* ensure 62.5 ms floor */ + while (16 * timeo < hz) + timeo *= 2; if (nmp->nm_timeouts > 0) timeo *= nfs_backoff[nmp->nm_timeouts - 1]; if (rep->r_rtt <= timeo) @@ -1404,11 +1497,15 @@ nfs_timer(arg) nmp->nm_sent < nmp->nm_cwnd) && (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))){ #if DIAGNOSTIC - if (rep->r_flags & R_SENT) { /* retry? */ - if (nfsprnttimo && nmp->nm_timeouts >= nfsprnttimo) - kprintf("nfs_timer %s f=0x%x nmtm=%d tms=%d rtt=%d tm=%d p#=%d\n", - nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_flag, nmp->nm_timeo, nmp->nm_timeouts, rttdiag, timeo, rep->r_procnum); + if (rep->r_flags & R_SENT && nfsprnttimo && + nmp->nm_timeouts >= nfsprnttimo) { + int t = proct[rep->r_procnum]; + if (t) + NFS_DPF(DUP, ("nfs_timer %s nmtm=%d tms=%d rtt=%d tm=%d p=%d A=%d D=%d\n", nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_timeo, nmp->nm_timeouts, rttdiag, timeo, rep->r_procnum, nmp->nm_srtt[t-1], nmp->nm_sdrtt[t-1])); + else + NFS_DPF(DUP, ("nfs_timer %s nmtm=%d tms=%d rtt=%d tm=%d p=%d\n", nmp->nm_mountp->mnt_stat.f_mntfromname, nmp->nm_timeo, nmp->nm_timeouts, rttdiag, timeo, rep->r_procnum)); } + nfsdup(rep); #endif if ((nmp->nm_flag & NFSMNT_NOCONN) == 0) error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, m, @@ -1540,12 +1637,6 @@ nfs_sndunlock(flagp) } } -#if DIAGNOSTIC -uint nfstraceindx = 0; -struct nfstracerec nfstracebuf[NFSTBUFSIZ] = {{0,0,0,0}}; -uint nfstracemask = 0; /* enables trace points 0 to 31 (right to left) */ -#endif /* DIAGNOSTIC */ - static int nfs_rcvlock(rep) register struct nfsreq *rep;