- aio.iov_base = (caddr_t) &len;
- aio.iov_len = sizeof(u_long);
- auio.uio_iov = &aio;
- auio.uio_iovcnt = 1;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_offset = 0;
- auio.uio_resid = sizeof(u_long);
- auio.uio_procp = p;
- do {
- rcvflg = MSG_WAITALL;
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- error = soreceive(so, (struct sockaddr **)0, &auio,
- (struct mbuf **)0, (struct mbuf **)0, &rcvflg);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- if (!rep->r_nmp) /* if unmounted then bailout */
- goto shutout;
- if (error == EWOULDBLOCK && rep) {
- if (rep->r_flags & R_SOFTTERM)
- return (EINTR);
- }
- } while (error == EWOULDBLOCK);
- if (!error && auio.uio_resid > 0) {
- log(LOG_INFO,
- "short receive (%d/%d) from nfs server %s\n",
- sizeof(u_long) - auio.uio_resid,
- sizeof(u_long),
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = EPIPE;
- }
- if (error)
- goto errout;
- len = ntohl(len) & ~0x80000000;
- /*
- * This is SERIOUS! We are out of sync with the sender
- * and forcing a disconnect/reconnect is all I can do.
- */
- if (len > NFS_MAXPACKET) {
- log(LOG_ERR, "%s (%d) from nfs server %s\n",
- "impossible packet length",
- len,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- error = EFBIG;
- goto errout;
- }
- auio.uio_resid = len;
-
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
- do {
- rcvflg = MSG_WAITALL;
- error = soreceive(so, (struct sockaddr **)0,
- &auio, mp, (struct mbuf **)0, &rcvflg);
- if (!rep->r_nmp) /* if unmounted then bailout */ {
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- goto shutout;
- }
- } while (error == EWOULDBLOCK || error == EINTR ||
- error == ERESTART);
-
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ error = 0;
+ len = 0;
+ lastfragment = 0;
+ mlast = NULL;
+ while (!error && !lastfragment) {
+ aio.iov_base = (uintptr_t) &fraglen;
+ aio.iov_len = sizeof(u_long);
+ bzero(&msg, sizeof(msg));
+ msg.msg_iov = (struct iovec *) &aio;
+ msg.msg_iovlen = 1;
+ do {
+ error = sock_receive(so, &msg, MSG_WAITALL, &rcvlen);
+ if (!rep->r_nmp) /* if unmounted then bailout */
+ goto shutout;
+ if (error == EWOULDBLOCK && rep) {
+ error2 = nfs_sigintr(rep->r_nmp, rep, p);
+ if (error2)
+ error = error2;
+ }
+ } while (error == EWOULDBLOCK);
+ if (!error && rcvlen < aio.iov_len) {
+ /* only log a message if we got a partial word */
+ if (rcvlen != 0)
+ log(LOG_INFO,
+ "short receive (%d/%d) from nfs server %s\n",
+ rcvlen, sizeof(u_long),
+ vfs_statfs(rep->r_nmp->nm_mountp)->f_mntfromname);
+ error = EPIPE;
+ }
+ if (error)
+ goto errout;
+ lastfragment = ntohl(fraglen) & 0x80000000;
+ fraglen = ntohl(fraglen) & ~0x80000000;
+ len += fraglen;
+ /*
+ * This is SERIOUS! We are out of sync with the sender
+ * and forcing a disconnect/reconnect is all I can do.
+ */
+ if (len > NFS_MAXPACKET) {
+ log(LOG_ERR, "%s (%d) from nfs server %s\n",
+ "impossible RPC record length", len,
+ vfs_statfs(rep->r_nmp->nm_mountp)->f_mntfromname);
+ error = EFBIG;
+ goto errout;
+ }