From 29efbf0d8f0bf1bc26410b1f902ca27b6250c487 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 20 Apr 2007 05:42:25 +0000 Subject: [PATCH] Clean up the so_pru_soreceive() API a bit to make it easier to read mbuf chains without having to use a fake UIO. --- sys/kern/uipc_socket.c | 96 ++++++++++++++++++------------ sys/net/netmsg.h | 4 +- sys/netgraph/ksocket/ng_ksocket.c | 32 +++++----- sys/netproto/ncp/ncp_ncp.c | 28 +++++---- sys/netproto/ncp/ncp_sock.c | 53 ++++++++--------- sys/netproto/ncp/ncp_sock.h | 4 +- sys/netproto/smb/smb_trantcp.c | 58 +++++++++--------- sys/sys/protosw.h | 9 ++- sys/sys/socketops.h | 8 +-- sys/sys/socketvar.h | 25 +++++++- sys/vfs/fifofs/fifo_vnops.c | 5 +- sys/vfs/nfs/krpc_subr.c | 13 ++-- sys/vfs/nfs/nfs_socket.c | 122 +++++++++++++++++++++----------------- sys/vfs/portal/portal_vnops.c | 23 +++---- 14 files changed, 272 insertions(+), 208 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index e72007ba95..ffa8cf05d7 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -65,7 +65,7 @@ * * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 * $FreeBSD: src/sys/kern/uipc_socket.c,v 1.68.2.24 2003/11/11 17:18:18 silby Exp $ - * $DragonFly: src/sys/kern/uipc_socket.c,v 1.43 2007/03/04 18:51:59 swildner Exp $ + * $DragonFly: src/sys/kern/uipc_socket.c,v 1.44 2007/04/20 05:42:20 dillon Exp $ */ #include "opt_inet.h" @@ -763,16 +763,21 @@ out: */ int soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, - struct mbuf **mp0, struct mbuf **controlp, int *flagsp) + struct sorecv_direct *sio, struct mbuf **controlp, int *flagsp) { - struct mbuf *m, *n, **mp; + struct mbuf *m, *n; struct mbuf *free_chain = NULL; int flags, len, error, offset; struct protosw *pr = so->so_proto; int moff, type = 0; - int orig_resid = uio->uio_resid; + int resid, orig_resid; + + if (uio) + resid = uio->uio_resid; + else + resid = sio->maxlen - sio->len; + orig_resid = resid; - mp = mp0; if (psa) *psa = NULL; if (controlp) @@ -788,19 +793,30 @@ soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, error = so_pru_rcvoob(so, m, flags & MSG_PEEK); if (error) goto bad; - do { - error = uiomove(mtod(m, caddr_t), - (int) min(uio->uio_resid, m->m_len), uio); - m = m_free(m); - } while (uio->uio_resid && error == 0 && m); + if (sio) { + do { + *sio->mapp = m; + sio->mapp = &m->m_next; + m = m->m_next; + *sio->mapp = NULL; + resid -= m->m_len; + sio->len += m->m_len; + } while (resid > 0 && m); + } else { + do { + uio->uio_resid = resid; + error = uiomove(mtod(m, caddr_t), + (int)min(resid, m->m_len), uio); + resid = uio->uio_resid; + m = m_free(m); + } while (uio->uio_resid && error == 0 && m); + } bad: if (m) m_freem(m); return (error); } - if (mp) - *mp = NULL; - if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) + if (so->so_state & SS_ISCONFIRMING && resid) so_pru_rcvd(so, 0); restart: @@ -822,9 +838,9 @@ restart: * a short count if a timeout or signal occurs after we start. */ if (m == NULL || (((flags & MSG_DONTWAIT) == 0 && - so->so_rcv.sb_cc < uio->uio_resid) && + so->so_rcv.sb_cc < resid) && (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || - ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && + ((flags & MSG_WAITALL) && resid <= so->so_rcv.sb_hiwat)) && m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) { KASSERT(m != NULL || !so->so_rcv.sb_cc, ("receive 1")); if (so->so_error) { @@ -852,7 +868,7 @@ restart: error = ENOTCONN; goto release; } - if (uio->uio_resid == 0) + if (resid == 0) goto release; if (flags & (MSG_FNONBLOCKING|MSG_DONTWAIT)) { error = EWOULDBLOCK; @@ -866,7 +882,7 @@ restart: goto restart; } dontblock: - if (uio->uio_td && uio->uio_td->td_proc) + if (uio && uio->uio_td && uio->uio_td->td_proc) uio->uio_td->td_lwp->lwp_ru.ru_msgrcv++; /* @@ -948,7 +964,7 @@ dontblock: */ moff = 0; offset = 0; - while (m && uio->uio_resid > 0 && error == 0) { + while (m && resid > 0 && error == 0) { if (m->m_type == MT_OOBDATA) { if (type != MT_OOBDATA) break; @@ -958,27 +974,27 @@ dontblock: KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER, ("receive 3")); so->so_state &= ~SS_RCVATMARK; - len = uio->uio_resid; + len = resid; if (so->so_oobmark && len > so->so_oobmark - offset) len = so->so_oobmark - offset; if (len > m->m_len - moff) len = m->m_len - moff; + /* - * If mp is set, just pass back the mbufs. - * Otherwise copy them out via the uio, then free. - * Sockbuf must be consistent here (points to current mbuf, - * it points to next record) when we drop priority; - * we must note any additions to the sockbuf when we - * block interrupts again. + * Copy out to the UIO or pass the mbufs back to the SIO. + * The SIO is dealt with when we eat the mbuf, but deal + * with the resid here either way. */ - if (mp == NULL) { + if (uio) { crit_exit(); - error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); + uio->uio_resid = resid; + error = uiomove(mtod(m, caddr_t) + moff, len, uio); + resid = uio->uio_resid; crit_enter(); if (error) goto release; } else { - uio->uio_resid -= len; + resid -= len; } /* @@ -995,10 +1011,11 @@ dontblock: m = m->m_next; moff = 0; } else { - if (mp) { + if (sio) { n = sbunlinkmbuf(&so->so_rcv, m, NULL); - *mp = m; - mp = &m->m_next; + *sio->mapp = m; + sio->mapp = &m->m_next; + sio->len += m->m_len; m = n; } else { m = sbunlinkmbuf(&so->so_rcv, m, &free_chain); @@ -1008,8 +1025,11 @@ dontblock: if (flags & MSG_PEEK) { moff += len; } else { - if (mp) - *mp = m_copym(m, 0, len, MB_WAIT); + if (sio) { + *sio->mapp= m_copym(m, 0, len, MB_WAIT); + sio->mapp = &m->m_next; + sio->len += len; + } m->m_data += len; m->m_len -= len; so->so_rcv.sb_cc -= len; @@ -1032,14 +1052,14 @@ dontblock: break; /* * If the MSG_WAITALL flag is set (for non-atomic socket), - * we must not quit until "uio->uio_resid == 0" or an error + * we must not quit until resid == 0 or an error * termination. If a signal/timeout occurs, return * with a short count but without error. * Keep sockbuf locked against other readers. */ - while (flags & MSG_WAITALL && m == NULL && - uio->uio_resid > 0 && !sosendallatonce(so) && - so->so_rcv.sb_mb == NULL) { + while ((flags & MSG_WAITALL) && m == NULL && + resid > 0 && !sosendallatonce(so) && + so->so_rcv.sb_mb == NULL) { if (so->so_error || so->so_state & SS_CANTRCVMORE) break; /* @@ -1077,7 +1097,7 @@ dontblock: so_pru_rcvd(so, flags); } - if (orig_resid == uio->uio_resid && orig_resid && + if (orig_resid == resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { sbunlock(&so->so_rcv); crit_exit(); diff --git a/sys/net/netmsg.h b/sys/net/netmsg.h index a21ba5fec7..29f24eaaf1 100644 --- a/sys/net/netmsg.h +++ b/sys/net/netmsg.h @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $DragonFly: src/sys/net/netmsg.h,v 1.3 2006/05/20 04:42:08 dillon Exp $ + * $DragonFly: src/sys/net/netmsg.h,v 1.4 2007/04/20 05:42:21 dillon Exp $ */ #ifndef _NET_NETMSG_H_ @@ -188,7 +188,7 @@ struct netmsg_pru_soreceive { struct socket *nm_so; struct sockaddr **nm_paddr; struct uio *nm_uio; - struct mbuf **nm_mp0; + struct sorecv_direct *nm_sio; struct mbuf **nm_controlp; int *nm_flagsp; }; diff --git a/sys/netgraph/ksocket/ng_ksocket.c b/sys/netgraph/ksocket/ng_ksocket.c index 9ad72c929f..75b2934843 100644 --- a/sys/netgraph/ksocket/ng_ksocket.c +++ b/sys/netgraph/ksocket/ng_ksocket.c @@ -37,7 +37,7 @@ * Author: Archie Cobbs * * $FreeBSD: src/sys/netgraph/ng_ksocket.c,v 1.5.2.14 2003/08/24 08:24:38 hsu Exp $ - * $DragonFly: src/sys/netgraph/ksocket/ng_ksocket.c,v 1.12 2006/12/20 19:14:43 dillon Exp $ + * $DragonFly: src/sys/netgraph/ksocket/ng_ksocket.c,v 1.13 2007/04/20 05:42:22 dillon Exp $ * $Whistle: ng_ksocket.c,v 1.1 1999/11/16 20:04:40 archie Exp $ */ @@ -991,10 +991,8 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) { const node_p node = arg; const priv_p priv = node->private; - struct mbuf *m; struct ng_mesg *response; - struct uio auio; - int flags, error; + int error; crit_enter(); @@ -1051,22 +1049,25 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) } /* Read and forward available mbuf's */ - auio.uio_td = NULL; - auio.uio_resid = 1000000000; - flags = MSG_DONTWAIT; while (1) { struct sockaddr *sa = NULL; + struct sorecv_direct sio; meta_p meta = NULL; struct mbuf *n; + int flags; + + sorecv_direct_init(&sio, 1000000000); + flags = MSG_DONTWAIT; /* Try to get next packet from socket */ - if ((error = so_pru_soreceive(so, - (so->so_state & SS_ISCONNECTED) ? NULL : &sa, - &auio, &m, (struct mbuf **)0, &flags)) != 0) + error = so_pru_soreceive(so, + ((so->so_state & SS_ISCONNECTED) ? NULL : &sa), + NULL, &sio, NULL, &flags); + if (error) break; /* See if we got anything */ - if (m == NULL) { + if (sio.m0 == NULL) { if (sa != NULL) FREE(sa, M_SONAME); break; @@ -1074,8 +1075,9 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) /* Don't trust the various socket layers to get the packet header and length correct (eg. kern/15175) */ - for (n = m, m->m_pkthdr.len = 0; n != NULL; n = n->m_next) - m->m_pkthdr.len += n->m_len; + sio.m0->m_pkthdr.len = 0; + for (n = sio.m0; n != NULL; n = n->m_next) + sio.m0->m_pkthdr.len += n->m_len; /* Put peer's socket address (if any) into a meta info blob */ if (sa != NULL) { @@ -1100,7 +1102,7 @@ ng_ksocket_incoming(struct socket *so, void *arg, int waitflag) FREE(sa, M_SONAME); } sendit: /* Forward data with optional peer sockaddr as meta info */ - NG_SEND_DATA(error, priv->hook, m, meta); + NG_SEND_DATA(error, priv->hook, sio.m0, meta); } /* @@ -1108,6 +1110,8 @@ sendit: /* Forward data with optional peer sockaddr as meta info */ * to indicate end-of-file. */ if (so->so_state & SS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) { + struct mbuf *m; + MGETHDR(m, waitflag, MT_DATA); if (m != NULL) { m->m_len = m->m_pkthdr.len = 0; diff --git a/sys/netproto/ncp/ncp_ncp.c b/sys/netproto/ncp/ncp_ncp.c index ce036d453b..5252e3fd8d 100644 --- a/sys/netproto/ncp/ncp_ncp.c +++ b/sys/netproto/ncp/ncp_ncp.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netncp/ncp_ncp.c,v 1.3 1999/10/29 10:21:07 bp Exp $ - * $DragonFly: src/sys/netproto/ncp/ncp_ncp.c,v 1.13 2007/02/25 23:17:13 corecode Exp $ + * $DragonFly: src/sys/netproto/ncp/ncp_ncp.c,v 1.14 2007/04/20 05:42:23 dillon Exp $ * * Core of NCP protocol */ @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef IPX #include @@ -211,9 +212,13 @@ ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) { */ crit_enter(); while (1/*so->so_rcv.sb_cc*/) { - if (ncp_poll(so,POLLIN) == 0) break; - if (ncp_sock_recv(so,&m,&len) != 0) break; - m_freem(m); + struct sorecv_direct sio; + + if (ncp_poll(so, POLLIN) == 0) + break; + if (ncp_sock_recv(so, &sio) != 0) + break; + m_freem(sio.m0); } rq = mtod(rqp->rq,struct ncp_rqhdr *); rq->seq = conn->seq; @@ -271,13 +276,14 @@ ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) { gotpacket = 0; /* nothing good found */ dosend = 1; /* resend rq if error */ for (;;) { + struct sorecv_direct sio; + error = 0; if (ncp_poll(so,POLLIN) == 0) break; -/* if (so->so_rcv.sb_cc == 0) { - break; - }*/ - error = ncp_sock_recv(so,&m,&len); + error = ncp_sock_recv(so, &sio); if (error) break; /* must be more checks !!! */ + + m = sio.m0; if (m->m_len < sizeof(*rp)) { m = m_pullup(m, sizeof(*rp)); if (m == NULL) { @@ -286,7 +292,7 @@ ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) { } } rp = mtod(m, struct ncp_rphdr*); - if (len == sizeof(*rp) && rp->type == NCP_POSITIVE_ACK) { + if (sio.len == sizeof(*rp) && rp->type == NCP_POSITIVE_ACK) { NCPSDEBUG("got positive acknowledge\n"); m_freem(m); rqp->rexmit = conn->li.retry_count; @@ -294,7 +300,7 @@ ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) { continue; } NCPSDEBUG("recv:%04x c=%d l=%d s=%d t=%d cc=%02x cs=%02x\n",rp->type, - (rp->conn_high << 8) + rp->conn_low, len, rp->seq, rp->task, + (rp->conn_high << 8) + rp->conn_low, sio.len, rp->seq, rp->task, rp->completion_code, rp->connection_state); NCPDDEBUG(m); if ( (rp->type == NCP_REPLY) && @@ -311,7 +317,7 @@ ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) { } else { gotpacket = 1; mreply = m; - plen = len; + plen = sio.len; } continue; /* look up other for other packets */ } diff --git a/sys/netproto/ncp/ncp_sock.c b/sys/netproto/ncp/ncp_sock.c index c7146b1a41..bf1dab19bd 100644 --- a/sys/netproto/ncp/ncp_sock.c +++ b/sys/netproto/ncp/ncp_sock.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netncp/ncp_sock.c,v 1.2 1999/10/12 10:36:59 bp Exp $ - * $DragonFly: src/sys/netproto/ncp/ncp_sock.c,v 1.16 2007/02/18 16:13:27 corecode Exp $ + * $DragonFly: src/sys/netproto/ncp/ncp_sock.c,v 1.17 2007/04/20 05:42:23 dillon Exp $ * * Low level socket routines */ @@ -139,23 +139,16 @@ ncp_getsockname(struct socket *so, caddr_t asa, int *alen) { } #endif int -ncp_sock_recv(struct socket *so, struct mbuf **mp, int *rlen) +ncp_sock_recv(struct socket *so, struct sorecv_direct *sio) { - struct uio auio; struct thread *td = curthread; /* XXX */ - int error,flags,len; - - auio.uio_resid = len = 1000000; - auio.uio_td = td; + int error, flags; + + sio->len = 1000000; /* limit data returned (inexact, hint only) */ + sio->m0 = NULL; flags = MSG_DONTWAIT; -/* error = so_pru_soreceive(so, NULL, &auio, NULL, NULL, &flags); */ - error = so_pru_soreceive(so, NULL, &auio, mp, NULL, &flags); - *rlen = len - auio.uio_resid; -/* if (!error) { - *rlen=iov.iov_len; - } else - *rlen=0;*/ + error = so_pru_soreceive(so, NULL, NULL, sio, NULL, &flags); #ifdef NCP_SOCKET_DEBUG if (error) kprintf("ncp_recv: err=%d\n", error); @@ -400,32 +393,38 @@ ncp_sock_disconnect(struct ncp_conn *conn) { static void ncp_watchdog(struct ncp_conn *conn) { char *buf; - struct mbuf *m; int error, len, flags; struct socket *so; struct sockaddr *sa; - struct uio auio; + struct sorecv_direct sio; sa = NULL; while (conn->wdg_so) { /* not a loop */ so = conn->wdg_so; - auio.uio_resid = len = 1000000; - auio.uio_td = curthread; + sorecv_direct_init(&sio, 1000000); flags = MSG_DONTWAIT; - error = so_pru_soreceive(so, (struct sockaddr**)&sa, &auio, &m, - NULL, &flags); - if (error) break; - len -= auio.uio_resid; + error = so_pru_soreceive(so, (struct sockaddr**)&sa, + NULL, &sio, NULL, &flags); + if (error) + break; + len = sio.len; NCPSDEBUG("got watch dog %d\n",len); - if (len != 2) break; - buf = mtod(m, char*); - if (buf[1] != '?') break; + if (len != 2) { + m_freem(sio.m0); + break; + } + buf = mtod(sio.m0, char *); + if (buf[1] != '?') { + m_freem(sio.m0); + break; + } buf[1] = 'Y'; - error = so_pru_sosend(so, sa, NULL, m, NULL, 0, curthread); + error = so_pru_sosend(so, sa, NULL, sio.m0, NULL, 0, curthread); NCPSDEBUG("send watch dog %d\n",error); break; } - if (sa) FREE(sa, M_SONAME); + if (sa) + FREE(sa, M_SONAME); return; } #endif /* IPX */ diff --git a/sys/netproto/ncp/ncp_sock.h b/sys/netproto/ncp/ncp_sock.h index e82f1dddf3..d7b5c967b6 100644 --- a/sys/netproto/ncp/ncp_sock.h +++ b/sys/netproto/ncp/ncp_sock.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netncp/ncp_sock.h,v 1.3 2000/01/14 19:54:39 bde Exp $ - * $DragonFly: src/sys/netproto/ncp/ncp_sock.h,v 1.3 2003/06/25 05:56:05 dillon Exp $ + * $DragonFly: src/sys/netproto/ncp/ncp_sock.h,v 1.4 2007/04/20 05:42:23 dillon Exp $ */ #ifndef _NETNCP_NCP_SOCK_H_ #define _NETNCP_NCP_SOCK_H_ @@ -45,7 +45,7 @@ struct timeval; int ncp_sock_connect_ipx(struct ncp_conn *); int ncp_sock_connect_in(struct ncp_conn *); -int ncp_sock_recv(struct socket *so, struct mbuf **mp, int *rlen); +int ncp_sock_recv(struct socket *so, struct sorecv_direct *sio); int ncp_sock_send(struct socket *so, struct mbuf *data, struct ncp_rq *rqp); int ncp_sock_disconnect(struct ncp_conn *conn); int ncp_poll(struct socket *so, int events); diff --git a/sys/netproto/smb/smb_trantcp.c b/sys/netproto/smb/smb_trantcp.c index c33f801cd3..2eb287a2c6 100644 --- a/sys/netproto/smb/smb_trantcp.c +++ b/sys/netproto/smb/smb_trantcp.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_trantcp.c,v 1.3.2.1 2001/05/22 08:32:34 bp Exp $ - * $DragonFly: src/sys/netproto/smb/smb_trantcp.c,v 1.17 2007/02/18 16:13:27 corecode Exp $ + * $DragonFly: src/sys/netproto/smb/smb_trantcp.c,v 1.18 2007/04/20 05:42:24 dillon Exp $ */ #include #include @@ -371,67 +371,63 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp, u_int8_t *rpcodep, struct thread *td) { struct socket *so = nbp->nbp_tso; - struct uio auio; - struct mbuf *m; + struct sorecv_direct sio; u_int8_t rpcode; - int len; - int error, rcvflg; + int error, rcvflg, savelen; if (so == NULL) return ENOTCONN; + sio.len = 0; + sio.m0 = NULL; if (mpp) *mpp = NULL; + for(;;) { - m = NULL; - error = nbssn_recvhdr(nbp, &len, &rpcode, MSG_DONTWAIT, td); + error = nbssn_recvhdr(nbp, &savelen, &rpcode, MSG_DONTWAIT, td); if (so->so_state & (SS_ISDISCONNECTING | SS_ISDISCONNECTED | SS_CANTRCVMORE)) { nbp->nbp_state = NBST_CLOSED; NBDEBUG("session closed by peer\n"); - return ECONNRESET; + error = ECONNRESET; + break; } if (error) - return error; - if (len == 0 && nbp->nbp_state != NBST_SESSION) + break; + if (savelen == 0 && nbp->nbp_state != NBST_SESSION) break; if (rpcode == NB_SSN_KEEPALIVE) continue; - bzero(&auio, sizeof(auio)); - auio.uio_resid = len; - auio.uio_td = td; do { + sorecv_direct_init(&sio, savelen); rcvflg = MSG_WAITALL; - error = so_pru_soreceive(so, NULL, &auio, &m, NULL, - &rcvflg); + error = so_pru_soreceive(so, NULL, NULL, &sio, + NULL, &rcvflg); } while (error == EWOULDBLOCK || error == EINTR || error == ERESTART); if (error) break; - if (auio.uio_resid > 0) { + if (sio.len != savelen) { SMBERROR("packet is shorter than expected\n"); error = EPIPE; + m_freem(sio.m0); break; } - if (nbp->nbp_state == NBST_SESSION && - rpcode == NB_SSN_MESSAGE) + if (nbp->nbp_state == NBST_SESSION && rpcode == NB_SSN_MESSAGE) break; NBDEBUG("non-session packet %x\n", rpcode); - if (m) - m_freem(m); + m_freem(sio.m0); + sio.m0 = NULL; } - if (error) { - if (m) - m_freem(m); - return error; + if (error == 0) { + if (mpp) + *mpp = sio.m0; + else + m_freem(sio.m0); + *lenp = sio.len; + *rpcodep = rpcode; } - if (mpp) - *mpp = m; - else - m_freem(m); - *lenp = len; - *rpcodep = rpcode; - return 0; + return (error); } /* diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index 63a0e5718e..a9c94b804b 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -32,7 +32,7 @@ * * @(#)protosw.h 8.1 (Berkeley) 6/2/93 * $FreeBSD: src/sys/sys/protosw.h,v 1.28.2.2 2001/07/03 11:02:01 ume Exp $ - * $DragonFly: src/sys/sys/protosw.h,v 1.17 2006/05/21 05:43:47 dillon Exp $ + * $DragonFly: src/sys/sys/protosw.h,v 1.18 2007/04/20 05:42:24 dillon Exp $ */ #ifndef _SYS_PROTOSW_H_ @@ -186,6 +186,7 @@ struct ifnet; struct stat; struct ucred; struct uio; +struct sorecv_direct; struct pru_attach_info { struct rlimit *sb_rlimit; @@ -244,7 +245,8 @@ struct pr_usrreqs { struct thread *td); int (*pru_soreceive) (struct socket *so, struct sockaddr **paddr, - struct uio *uio, struct mbuf **mp0, + struct uio *uio, + struct sorecv_direct *sio, struct mbuf **controlp, int *flagsp); int (*pru_sopoll) (struct socket *so, int events, struct ucred *cred, struct thread *td); @@ -280,7 +282,8 @@ typedef int (*pru_sosend_fn_t) (struct socket *so, struct sockaddr *addr, struct mbuf *control, int flags, struct thread *td); typedef int (*pru_soreceive_fn_t) (struct socket *so, struct sockaddr **paddr, - struct uio *uio, struct mbuf **mp0, + struct uio *uio, + struct sorecv_direct *sio, struct mbuf **controlp, int *flagsp); typedef int (*pru_sopoll_fn_t) (struct socket *so, int events, diff --git a/sys/sys/socketops.h b/sys/sys/socketops.h index cfcdb6bb4b..a8601a5734 100644 --- a/sys/sys/socketops.h +++ b/sys/sys/socketops.h @@ -30,7 +30,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/socketops.h,v 1.9 2007/03/04 18:51:59 swildner Exp $ + * $DragonFly: src/sys/sys/socketops.h,v 1.10 2007/04/20 05:42:24 dillon Exp $ */ #ifndef _SOCKETOPS_H_ @@ -67,10 +67,10 @@ so_pru_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, static __inline int so_pru_soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, - struct mbuf **mp0, struct mbuf **controlp, int *flagsp) + struct sorecv_direct *sio, struct mbuf **controlp, int *flagsp) { - return ((*so->so_proto->pr_usrreqs->pru_soreceive)(so, paddr, uio, mp0, - controlp, flagsp)); + return ((*so->so_proto->pr_usrreqs->pru_soreceive)(so, paddr, uio, sio, + controlp, flagsp)); } int so_pru_abort (struct socket *so); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index acf3fd4ef6..1bd617eef9 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -32,7 +32,7 @@ * * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 * $FreeBSD: src/sys/sys/socketvar.h,v 1.46.2.10 2003/08/24 08:24:39 hsu Exp $ - * $DragonFly: src/sys/sys/socketvar.h,v 1.26 2006/06/13 10:12:04 dillon Exp $ + * $DragonFly: src/sys/sys/socketvar.h,v 1.27 2007/04/20 05:42:24 dillon Exp $ */ #ifndef _SYS_SOCKETVAR_H_ @@ -300,6 +300,27 @@ struct accept_filter { SLIST_ENTRY(accept_filter) accf_next; /* next on the list */ }; +/* + * Passed to so_pru_soreceive() instead of a UIO to directly obtain an + * mbuf chain. The sorecv_direct API allows mbufs to be directly + * transfered to the caller. + */ +struct sorecv_direct { + int len; + int maxlen; + struct mbuf *m0; + struct mbuf **mapp; +}; + +static __inline void +sorecv_direct_init(struct sorecv_direct *sio, int maxlen) +{ + sio->len = 0; + sio->maxlen = maxlen; + sio->m0 = NULL; + sio->mapp = &sio->m0; +} + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_PCB); MALLOC_DECLARE(M_SONAME); @@ -398,7 +419,7 @@ int soopt_mcopyout (struct sockopt *sopt, struct mbuf *m); int sopoll (struct socket *so, int events, struct ucred *cred, struct thread *td); int soreceive (struct socket *so, struct sockaddr **paddr, - struct uio *uio, struct mbuf **mp0, + struct uio *uio, struct sorecv_direct *sio, struct mbuf **controlp, int *flagsp); int soreserve (struct socket *so, u_long sndcc, u_long rcvcc, struct rlimit *rl); diff --git a/sys/vfs/fifofs/fifo_vnops.c b/sys/vfs/fifofs/fifo_vnops.c index 0eb5a334b6..1308a260bc 100644 --- a/sys/vfs/fifofs/fifo_vnops.c +++ b/sys/vfs/fifofs/fifo_vnops.c @@ -32,7 +32,7 @@ * * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 * $FreeBSD: src/sys/miscfs/fifofs/fifo_vnops.c,v 1.45.2.4 2003/04/22 10:11:24 bde Exp $ - * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.35 2006/12/23 01:41:29 swildner Exp $ + * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.36 2007/04/20 05:42:24 dillon Exp $ */ #include @@ -289,8 +289,7 @@ fifo_read(struct vop_read_args *ap) flags = 0; startresid = uio->uio_resid; vn_unlock(ap->a_vp); - error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, - (struct mbuf **)0, &flags); + error = soreceive(rso, NULL, uio, NULL, NULL, &flags); vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); return (error); } diff --git a/sys/vfs/nfs/krpc_subr.c b/sys/vfs/nfs/krpc_subr.c index 15c3c34560..6dee8b7333 100644 --- a/sys/vfs/nfs/krpc_subr.c +++ b/sys/vfs/nfs/krpc_subr.c @@ -1,6 +1,6 @@ /* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ /* $FreeBSD: src/sys/nfs/krpc_subr.c,v 1.13.2.1 2000/11/20 21:17:14 tegge Exp $ */ -/* $DragonFly: src/sys/vfs/nfs/krpc_subr.c,v 1.10 2006/12/23 01:41:29 swildner Exp $ */ +/* $DragonFly: src/sys/vfs/nfs/krpc_subr.c,v 1.11 2007/04/20 05:42:25 dillon Exp $ */ /* * Copyright (c) 1995 Gordon Ross, Adam Glass @@ -199,7 +199,7 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func, struct rpc_reply *reply; struct sockopt sopt; struct timeval tv; - struct uio auio; + struct sorecv_direct sio; int error, rcvflg, timo, secs, len; static u_int32_t xid = ~0xFF; u_int16_t tport; @@ -353,17 +353,18 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func, m_freem(m); m = NULL; } - bzero(&auio,sizeof(auio)); - auio.uio_resid = len = 1<<16; + len = 1 << 16; + sorecv_direct_init(&sio, len); rcvflg = 0; - error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); + error = soreceive(so, &from, NULL, &sio, NULL, &rcvflg); if (error == EWOULDBLOCK) { secs--; continue; } if (error) goto out; - len -= auio.uio_resid; + len -= sio.len; + m = sio.m0; /* Does the reply contain at least a header? */ if (len < MIN_REPLY_HDR) diff --git a/sys/vfs/nfs/nfs_socket.c b/sys/vfs/nfs/nfs_socket.c index 68ce06188d..afae07a22d 100644 --- a/sys/vfs/nfs/nfs_socket.c +++ b/sys/vfs/nfs/nfs_socket.c @@ -35,7 +35,7 @@ * * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95 * $FreeBSD: src/sys/nfs/nfs_socket.c,v 1.60.2.6 2003/03/26 01:44:46 alfred Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_socket.c,v 1.42 2007/02/25 23:17:13 corecode Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_socket.c,v 1.43 2007/04/20 05:42:25 dillon Exp $ */ /* @@ -531,6 +531,7 @@ static int nfs_receive(struct nfsreq *rep, struct sockaddr **aname, struct mbuf **mp) { struct socket *so; + struct sorecv_direct sio; struct uio auio; struct iovec aio; struct mbuf *m; @@ -543,8 +544,8 @@ nfs_receive(struct nfsreq *rep, struct sockaddr **aname, struct mbuf **mp) /* * Set up arguments for soreceive() */ - *mp = (struct mbuf *)0; - *aname = (struct sockaddr *)0; + *mp = NULL; + *aname = NULL; sotype = rep->r_nmp->nm_sotype; /* @@ -597,7 +598,10 @@ tryagain: } nfs_sndunlock(rep); if (sotype == SOCK_STREAM) { - aio.iov_base = (caddr_t) &len; + /* + * Get the length marker from the stream + */ + aio.iov_base = (caddr_t)&len; aio.iov_len = sizeof(u_int32_t); auio.uio_iov = &aio; auio.uio_iovcnt = 1; @@ -609,20 +613,18 @@ tryagain: do { rcvflg = MSG_WAITALL; error = so_pru_soreceive(so, NULL, &auio, NULL, - NULL, &rcvflg); + NULL, &rcvflg); if (error == EWOULDBLOCK && rep) { if (rep->r_flags & R_SOFTTERM) return (EINTR); } } while (error == EWOULDBLOCK); - if (!error && auio.uio_resid > 0) { + + if (error == 0 && auio.uio_resid > 0) { /* - * Don't log a 0 byte receive; it means - * that the socket has been closed, and - * can happen during normal operation - * (forcible unmount or Solaris server). + * Only log short packets if not EOF */ - if (auio.uio_resid != sizeof (u_int32_t)) + if (auio.uio_resid != sizeof(u_int32_t)) log(LOG_INFO, "short receive (%d/%d) from nfs server %s\n", (int)(sizeof(u_int32_t) - auio.uio_resid), @@ -645,59 +647,68 @@ tryagain: error = EFBIG; goto errout; } - auio.uio_resid = len; + + /* + * Get the rest of the packet as an mbuf chain + */ + sorecv_direct_init(&sio, len); do { rcvflg = MSG_WAITALL; - error = so_pru_soreceive(so, NULL, &auio, mp, - NULL, &rcvflg); + error = so_pru_soreceive(so, NULL, NULL, &sio, + NULL, &rcvflg); } while (error == EWOULDBLOCK || error == EINTR || error == ERESTART); - if (!error && auio.uio_resid > 0) { - if (len != auio.uio_resid) + if (error == 0 && sio.len != len) { + if (sio.len != 0) log(LOG_INFO, "short receive (%d/%d) from nfs server %s\n", len - auio.uio_resid, len, rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); error = EPIPE; } + *mp = sio.m0; } else { /* - * NB: Since uio_resid is big, MSG_WAITALL is ignored - * and soreceive() will return when it has either a - * control msg or a data msg. + * Non-stream, so get the whole packet by not + * specifying MSG_WAITALL and by specifying a large + * length. + * * We have no use for control msg., but must grab them * and then throw them away so we know what is going * on. */ - auio.uio_resid = len = 100000000; /* Anything Big */ - auio.uio_td = td; + sorecv_direct_init(&sio, 100000000); do { rcvflg = 0; - error = so_pru_soreceive(so, NULL, &auio, mp, - &control, &rcvflg); + error = so_pru_soreceive(so, NULL, NULL, &sio, + &control, &rcvflg); if (control) m_freem(control); if (error == EWOULDBLOCK && rep) { - if (rep->r_flags & R_SOFTTERM) + if (rep->r_flags & R_SOFTTERM) { + m_freem(sio.m0); return (EINTR); + } } } while (error == EWOULDBLOCK || - (!error && *mp == NULL && control)); + (error == 0 && sio.m0 == NULL && control)); if ((rcvflg & MSG_EOR) == 0) kprintf("Egad!!\n"); - if (!error && *mp == NULL) + if (error == 0 && sio.m0 == NULL) error = EPIPE; - len -= auio.uio_resid; + len = sio.len; + *mp = sio.m0; } errout: if (error && error != EINTR && error != ERESTART) { m_freem(*mp); - *mp = (struct mbuf *)0; - if (error != EPIPE) + *mp = NULL; + if (error != EPIPE) { log(LOG_INFO, "receive error %d from nfs server %s\n", error, rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); + } error = nfs_sndlock(rep); if (!error) { error = nfs_reconnect(rep); @@ -711,24 +722,26 @@ errout: if ((so = rep->r_nmp->nm_so) == NULL) return (EACCES); if (so->so_state & SS_ISCONNECTED) - getnam = (struct sockaddr **)0; + getnam = NULL; else getnam = aname; - auio.uio_resid = len = 1000000; - auio.uio_td = td; + sorecv_direct_init(&sio, 100000000); do { rcvflg = 0; - error = so_pru_soreceive(so, getnam, &auio, mp, NULL, - &rcvflg); + error = so_pru_soreceive(so, getnam, NULL, &sio, + NULL, &rcvflg); if (error == EWOULDBLOCK && - (rep->r_flags & R_SOFTTERM)) + (rep->r_flags & R_SOFTTERM)) { + m_freem(sio.m0); return (EINTR); + } } while (error == EWOULDBLOCK); - len -= auio.uio_resid; + len = sio.len; + *mp = sio.m0; } if (error) { m_freem(*mp); - *mp = (struct mbuf *)0; + *mp = NULL; } /* * Search for any mbufs that are not a multiple of 4 bytes long @@ -2025,9 +2038,8 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) { struct nfssvc_sock *slp = (struct nfssvc_sock *)arg; struct mbuf *m; - struct mbuf *mp; struct sockaddr *nam; - struct uio auio; + struct sorecv_direct sio; int flags, error; int nparallel_wakeup = 0; @@ -2058,7 +2070,6 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) * Handle protocol specifics to parse an RPC request. We always * pull from the socket using non-blocking I/O. */ - auio.uio_td = NULL; if (so->so_type == SOCK_STREAM) { /* * The data has to be read in an orderly fashion from a TCP @@ -2079,12 +2090,13 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) slp->ns_flag |= SLP_GETSTREAM; /* - * Do soreceive(). + * Do soreceive(). Pull out as much data as possible without + * blocking. */ - auio.uio_resid = 1000000000; + sorecv_direct_init(&sio, 1000000000); flags = MSG_DONTWAIT; - error = so_pru_soreceive(so, &nam, &auio, &mp, NULL, &flags); - if (error || mp == (struct mbuf *)0) { + error = so_pru_soreceive(so, &nam, NULL, &sio, NULL, &flags); + if (error || sio.m0 == NULL) { if (error == EWOULDBLOCK) slp->ns_flag |= SLP_NEEDQ; else @@ -2092,13 +2104,13 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) slp->ns_flag &= ~SLP_GETSTREAM; goto dorecs; } - m = mp; + m = sio.m0; if (slp->ns_rawend) { slp->ns_rawend->m_next = m; - slp->ns_cc += 1000000000 - auio.uio_resid; + slp->ns_cc += sio.len; } else { slp->ns_raw = m; - slp->ns_cc = 1000000000 - auio.uio_resid; + slp->ns_cc = sio.len; } while (m->m_next) m = m->m_next; @@ -2122,11 +2134,11 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) * to get the whole batch. */ do { - auio.uio_resid = 1000000000; + sorecv_direct_init(&sio, 1000000000); flags = MSG_DONTWAIT; - error = so_pru_soreceive(so, &nam, &auio, &mp, NULL, - &flags); - if (mp) { + error = so_pru_soreceive(so, &nam, NULL, &sio, + NULL, &flags); + if (sio.m0) { struct nfsrv_rec *rec; int mf = (waitflag & MB_DONTWAIT) ? M_NOWAIT : M_WAITOK; @@ -2135,12 +2147,12 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) if (!rec) { if (nam) FREE(nam, M_SONAME); - m_freem(mp); + m_freem(sio.m0); continue; } - nfs_realign(&mp, 10 * NFSX_UNSIGNED); + nfs_realign(&sio.m0, 10 * NFSX_UNSIGNED); rec->nr_address = nam; - rec->nr_packet = mp; + rec->nr_packet = sio.m0; STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link); ++slp->ns_numrec; ++nparallel_wakeup; @@ -2152,7 +2164,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) goto dorecs; } } - } while (mp); + } while (sio.m0); } /* diff --git a/sys/vfs/portal/portal_vnops.c b/sys/vfs/portal/portal_vnops.c index 47e3ddd18b..9bb58abd76 100644 --- a/sys/vfs/portal/portal_vnops.c +++ b/sys/vfs/portal/portal_vnops.c @@ -36,7 +36,7 @@ * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/miscfs/portal/portal_vnops.c,v 1.38 1999/12/21 06:29:00 chris Exp $ - * $DragonFly: src/sys/vfs/portal/portal_vnops.c,v 1.33 2006/12/23 01:41:30 swildner Exp $ + * $DragonFly: src/sys/vfs/portal/portal_vnops.c,v 1.34 2007/04/20 05:42:25 dillon Exp $ */ /* @@ -211,6 +211,7 @@ portal_open(struct vop_open_args *ap) struct vnode *vp = ap->a_vp; struct uio auio; struct iovec aiov[2]; + struct sorecv_direct sio; int res; struct mbuf *cm = 0; struct cmsghdr *cmsg; @@ -322,19 +323,21 @@ portal_open(struct vop_open_args *ap) if (error) goto bad; - len = auio.uio_resid = sizeof(int); + len = sizeof(int); + sorecv_direct_init(&sio, len); do { - struct mbuf *m = 0; - int flags = MSG_WAITALL; - error = soreceive(so, (struct sockaddr **) 0, &auio, - &m, &cm, &flags); + struct mbuf *m; + int flags; + + flags = MSG_WAITALL; + error = soreceive(so, NULL, NULL, &sio, &cm, &flags); if (error) goto bad; /* * Grab an error code from the mbuf. */ - if (m) { + if ((m = sio.m0) != NULL) { m = m_pullup(m, sizeof(int)); /* Needed? */ if (m) { error = *(mtod(m, int *)); @@ -343,16 +346,16 @@ portal_open(struct vop_open_args *ap) error = EINVAL; } } else { - if (cm == 0) { + if (cm == NULL) { error = ECONNRESET; /* XXX */ #ifdef notdef break; #endif } } - } while (cm == 0 && auio.uio_resid == len && !error); + } while (cm == NULL && sio.len == 0 && !error); - if (cm == 0) + if (cm == NULL) goto bad; if (auio.uio_resid) { -- 2.11.4.GIT