Fix for a NFS/TCP client bug which would cause the NFS/TCP stream to get
out of sync under heavy loads, forcing frequent reconnets, causing EBADRPC errors etc.
This commit is contained in:
parent
03487601c2
commit
9f5b7dea42
@ -767,6 +767,20 @@ nfstcp_readable(struct socket *so, int bytes)
|
|||||||
|
|
||||||
#define nfstcp_marker_readable(so) nfstcp_readable(so, sizeof(u_int32_t))
|
#define nfstcp_marker_readable(so) nfstcp_readable(so, sizeof(u_int32_t))
|
||||||
|
|
||||||
|
static int
|
||||||
|
nfs_copy_len(struct mbuf *mp, char *buf, int len)
|
||||||
|
{
|
||||||
|
while (len > 0 && mp != NULL) {
|
||||||
|
int copylen = min(len, mp->m_len);
|
||||||
|
|
||||||
|
bcopy(mp->m_data, buf, copylen);
|
||||||
|
buf += copylen;
|
||||||
|
len -= copylen;
|
||||||
|
mp = mp->m_next;
|
||||||
|
}
|
||||||
|
return (len);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
||||||
{
|
{
|
||||||
@ -792,6 +806,8 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
|||||||
auio.uio_rw = UIO_READ;
|
auio.uio_rw = UIO_READ;
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
if (nmp->nm_nfstcpstate.flags & NFS_TCP_EXPECT_RPCMARKER) {
|
if (nmp->nm_nfstcpstate.flags & NFS_TCP_EXPECT_RPCMARKER) {
|
||||||
|
int resid;
|
||||||
|
|
||||||
if (!nfstcp_marker_readable(so)) {
|
if (!nfstcp_marker_readable(so)) {
|
||||||
/* Marker is not readable */
|
/* Marker is not readable */
|
||||||
return;
|
return;
|
||||||
@ -820,6 +836,21 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
|
|||||||
}
|
}
|
||||||
if (mp == NULL)
|
if (mp == NULL)
|
||||||
panic("nfs_clnt_tcp_soupcall: Got empty mbuf chain from sorecv\n");
|
panic("nfs_clnt_tcp_soupcall: Got empty mbuf chain from sorecv\n");
|
||||||
|
/*
|
||||||
|
* Sigh. We can't do the obvious thing here (which would
|
||||||
|
* be to have soreceive copy the length from mbufs for us).
|
||||||
|
* Calling uiomove() from the context of a socket callback
|
||||||
|
* (even for kernel-kernel copies) leads to LORs (since
|
||||||
|
* we hold network locks at this point).
|
||||||
|
*/
|
||||||
|
if ((resid = nfs_copy_len(mp, (char *)&len,
|
||||||
|
sizeof(u_int32_t)))) {
|
||||||
|
log(LOG_ERR, "%s (%d) from nfs server %s\n",
|
||||||
|
"Bad RPC HDR length",
|
||||||
|
(int)(sizeof(u_int32_t) - resid),
|
||||||
|
nmp->nm_mountp->mnt_stat.f_mntfromname);
|
||||||
|
goto mark_reconnect;
|
||||||
|
}
|
||||||
bcopy(mtod(mp, u_int32_t *), &len, sizeof(len));
|
bcopy(mtod(mp, u_int32_t *), &len, sizeof(len));
|
||||||
len = ntohl(len) & ~0x80000000;
|
len = ntohl(len) & ~0x80000000;
|
||||||
m_freem(mp);
|
m_freem(mp);
|
||||||
|
Loading…
Reference in New Issue
Block a user