soreceive_generic(), and sopoll_generic(). Add new functions sosend(),

soreceive(), and sopoll(), which are wrappers for pru_sosend,
pru_soreceive, and pru_sopoll, and are now used univerally by socket
consumers rather than either directly invoking the old so*() functions
or directly invoking the protocol switch method (about an even split
prior to this commit).

This completes an architectural change that was begun in 1996 to permit
protocols to provide substitute implementations, as now used by UDP.
Consumers now uniformly invoke sosend(), soreceive(), and sopoll() to
perform these operations on sockets -- in particular, distributed file
systems and socket system calls.

Architectural head nod:	sam, gnn, wollman
This commit is contained in:
Robert Watson 2006-07-24 15:20:08 +00:00
parent 8eb98847ea
commit b0668f7151
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160619
13 changed files with 99 additions and 69 deletions

View File

@ -88,7 +88,7 @@ soo_read(fp, uio, active_cred, flags, td)
return (error);
}
#endif
error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, uio, 0, 0, 0);
error = soreceive(so, 0, uio, 0, 0, 0);
NET_UNLOCK_GIANT();
return (error);
}
@ -115,8 +115,7 @@ soo_write(fp, uio, active_cred, flags, td)
return (error);
}
#endif
error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, uio, 0, 0, 0,
uio->uio_td);
error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td);
if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) {
PROC_LOCK(uio->uio_td->td_proc);
psignal(uio->uio_td->td_proc, SIGPIPE);
@ -243,8 +242,7 @@ soo_poll(fp, events, active_cred, td)
return (error);
}
#endif
error = (so->so_proto->pr_usrreqs->pru_sopoll)
(so, events, fp->f_cred, td);
error = sopoll(so, events, fp->f_cred, td);
NET_UNLOCK_GIANT();
return (error);

View File

@ -119,9 +119,9 @@ protosw_init(struct protosw *pr)
DEFAULT(pu->pru_rcvd, pru_rcvd_notsupp);
DEFAULT(pu->pru_rcvoob, pru_rcvoob_notsupp);
DEFAULT(pu->pru_sense, pru_sense_null);
DEFAULT(pu->pru_sosend, sosend);
DEFAULT(pu->pru_soreceive, soreceive);
DEFAULT(pu->pru_sopoll, sopoll);
DEFAULT(pu->pru_sosend, sosend_generic);
DEFAULT(pu->pru_soreceive, soreceive_generic);
DEFAULT(pu->pru_sopoll, sopoll_generic);
#undef DEFAULT
if (pr->pr_init)
(*pr->pr_init)();

View File

@ -1093,7 +1093,7 @@ sosend_dgram(so, addr, uio, top, control, flags, td)
*/
#define snderr(errno) { error = (errno); goto release; }
int
sosend(so, addr, uio, top, control, flags, td)
sosend_generic(so, addr, uio, top, control, flags, td)
struct socket *so;
struct sockaddr *addr;
struct uio *uio;
@ -1256,6 +1256,25 @@ sosend(so, addr, uio, top, control, flags, td)
}
#undef snderr
int
sosend(so, addr, uio, top, control, flags, td)
struct socket *so;
struct sockaddr *addr;
struct uio *uio;
struct mbuf *top;
struct mbuf *control;
int flags;
struct thread *td;
{
/* XXXRW: Temporary debugging. */
KASSERT(so->so_proto->pr_usrreqs->pru_sosend != sosend,
("sosend: protocol calls sosend"));
return (so->so_proto->pr_usrreqs->pru_sosend(so, addr, uio, top,
control, flags, td));
}
/*
* The part of soreceive() that implements reading non-inline out-of-band
* data from a socket. For more complete comments, see soreceive(), from
@ -1361,7 +1380,7 @@ sockbuf_pushsync(struct sockbuf *sb, struct mbuf *nextrecord)
* the count in uio_resid.
*/
int
soreceive(so, psa, uio, mp0, controlp, flagsp)
soreceive_generic(so, psa, uio, mp0, controlp, flagsp)
struct socket *so;
struct sockaddr **psa;
struct uio *uio;
@ -1801,6 +1820,24 @@ soreceive(so, psa, uio, mp0, controlp, flagsp)
return (error);
}
int
soreceive(so, psa, uio, mp0, controlp, flagsp)
struct socket *so;
struct sockaddr **psa;
struct uio *uio;
struct mbuf **mp0;
struct mbuf **controlp;
int *flagsp;
{
/* XXXRW: Temporary debugging. */
KASSERT(so->so_proto->pr_usrreqs->pru_soreceive != soreceive,
("soreceive: protocol calls soreceive"));
return (so->so_proto->pr_usrreqs->pru_soreceive(so, psa, uio, mp0,
controlp, flagsp));
}
int
soshutdown(so, how)
struct socket *so;
@ -2411,6 +2448,19 @@ int
sopoll(struct socket *so, int events, struct ucred *active_cred,
struct thread *td)
{
/* XXXRW: Temporary debugging. */
KASSERT(so->so_proto->pr_usrreqs->pru_sopoll != sopoll,
("sopoll: protocol calls sopoll"));
return (so->so_proto->pr_usrreqs->pru_sopoll(so, events, active_cred,
td));
}
int
sopoll_generic(struct socket *so, int events, struct ucred *active_cred,
struct thread *td)
{
int revents = 0;
SOCKBUF_LOCK(&so->so_snd);

View File

@ -803,8 +803,7 @@ kern_sendit(td, s, mp, flags, control, segflg)
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
0, control, flags, td);
error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
if (error) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@ -1020,8 +1019,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
(struct mbuf **)0,
error = soreceive(so, &fromsa, &auio, (struct mbuf **)0,
(mp->msg_control || controlp) ? &control : (struct mbuf **)0,
&mp->msg_flags);
if (error) {

View File

@ -786,9 +786,9 @@ struct pr_usrreqs uipc_usrreqs = {
.pru_sense = uipc_sense,
.pru_shutdown = uipc_shutdown,
.pru_sockaddr = uipc_sockaddr,
.pru_sosend = sosend,
.pru_soreceive = soreceive,
.pru_sopoll = sopoll,
.pru_sosend = sosend_generic,
.pru_soreceive = soreceive_generic,
.pru_sopoll = sopoll_generic,
.pru_close = uipc_close,
};

View File

@ -1558,8 +1558,8 @@ ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
flags = MSG_DONTWAIT;
m = NULL;
error = (*s->l2so->so_proto->pr_usrreqs->pru_soreceive)(s->l2so,
NULL, &uio, &m, (struct mbuf **) NULL, &flags);
error = soreceive(s->l2so, NULL, &uio, &m,
(struct mbuf **) NULL, &flags);
if (error != 0) {
if (error == EWOULDBLOCK)
return (0); /* XXX can happen? */
@ -1610,9 +1610,8 @@ ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
return (0); /* we are done */
/* Call send function on the L2CAP socket */
error = (*s->l2so->so_proto->pr_usrreqs->pru_sosend)
(s->l2so, NULL, NULL, m, NULL, 0,
curthread /* XXX */);
error = sosend(s->l2so, NULL, NULL, m, NULL, 0,
curthread /* XXX */);
if (error != 0) {
NG_BTSOCKET_RFCOMM_ERR(
"%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);

View File

@ -920,7 +920,7 @@ ng_ksocket_rcvdata(hook_p hook, item_p item)
sa = &stag->sa;
/* Send packet */
error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, sa, 0, m, 0, 0, td);
error = sosend(so, sa, 0, m, 0, 0, td);
return (error);
}
@ -1101,9 +1101,8 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
struct mbuf *n;
/* Try to get next packet from socket */
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
(so, (so->so_state & SS_ISCONNECTED) ? NULL : &sa,
&auio, &m, (struct mbuf **)0, &flags)) != 0)
if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ?
NULL : &sa, &auio, &m, (struct mbuf **)0, &flags)) != 0)
break;
/* See if we got anything */

View File

@ -139,10 +139,9 @@ int ncp_sock_recv(struct socket *so, struct mbuf **mp, int *rlen)
auio.uio_td = td;
flags = MSG_DONTWAIT;
/* error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, &auio,
(struct mbuf **)0, (struct mbuf **)0, &flags);*/
error = so->so_proto->pr_usrreqs->pru_soreceive(so, 0, &auio,
mp, (struct mbuf **)0, &flags);
/* error = soreceive(so, 0, &auio, (struct mbuf **)0, (struct mbuf **)0,
&flags);*/
error = soreceive(so, 0, &auio, mp, (struct mbuf **)0, &flags);
*rlen = len - auio.uio_resid;
/* if (!error) {
*rlen=iov.iov_len;
@ -168,7 +167,7 @@ ncp_sock_send(struct socket *so, struct mbuf *top, struct ncp_rq *rqp)
for (;;) {
m = m_copym(top, 0, M_COPYALL, M_TRYWAIT);
/* NCPDDEBUG(m);*/
error = so->so_proto->pr_usrreqs->pru_sosend(so, to, 0, m, 0, flags, td);
error = sosend(so, to, 0, m, 0, flags, td);
if (error == 0 || error == EINTR || error == ENETDOWN)
break;
if (rqp->rexmit == 0) break;
@ -189,7 +188,7 @@ ncp_poll(struct socket *so, int events)
struct thread *td = curthread;
struct ucred *cred = NULL;
return so->so_proto->pr_usrreqs->pru_sopoll(so, events, cred, td);
return (sopoll(so, events, cred, td));
}
int
@ -443,8 +442,8 @@ ncp_watchdog(struct ncp_conn *conn) {
auio.uio_resid = len = 1000000;
auio.uio_td = curthread;
flags = MSG_DONTWAIT;
error = so->so_proto->pr_usrreqs->pru_soreceive(so,
(struct sockaddr**)&sa, &auio, &m, (struct mbuf**)0, &flags);
error = soreceive(so, (struct sockaddr**)&sa, &auio, &m,
(struct mbuf**)0, &flags);
if (error) break;
len -= auio.uio_resid;
NCPSDEBUG("got watch dog %d\n",len);
@ -452,7 +451,7 @@ ncp_watchdog(struct ncp_conn *conn) {
buf = mtod(m, char*);
if (buf[1] != '?') break;
buf[1] = 'Y';
error = so->so_proto->pr_usrreqs->pru_sosend(so, (struct sockaddr*)sa, 0, m, 0, 0, curthread);
error = sosend(so, (struct sockaddr*)sa, 0, m, 0, 0, curthread);
NCPSDEBUG("send watch dog %d\n",error);
break;
}

View File

@ -75,8 +75,7 @@ SYSCTL_DECL(_net_smb);
SYSCTL_INT(_net_smb, OID_AUTO, tcpsndbuf, CTLFLAG_RW, &smb_tcpsndbuf, 0, "");
SYSCTL_INT(_net_smb, OID_AUTO, tcprcvbuf, CTLFLAG_RW, &smb_tcprcvbuf, 0, "");
#define nb_sosend(so,m,flags,td) (so)->so_proto->pr_usrreqs->pru_sosend( \
so, NULL, 0, m, 0, flags, td)
#define nb_sosend(so,m,flags,td) sosend(so, NULL, 0, m, 0, flags, td)
static int nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
u_int8_t *rpcodep, struct thread *td);
@ -98,8 +97,7 @@ nb_setsockopt_int(struct socket *so, int level, int name, int val)
static __inline int
nb_poll(struct nbpcb *nbp, int events, struct thread *td)
{
return nbp->nbp_tso->so_proto->pr_usrreqs->pru_sopoll(nbp->nbp_tso,
events, NULL, td);
return sopoll(nbp->nbp_tso, events, NULL, td);
}
static int
@ -377,8 +375,7 @@ nbssn_recvhdr(struct nbpcb *nbp, int *lenp,
auio.uio_offset = 0;
auio.uio_resid = sizeof(len);
auio.uio_td = td;
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, (struct sockaddr **)NULL, &auio,
error = soreceive(so, (struct sockaddr **)NULL, &auio,
(struct mbuf **)NULL, (struct mbuf **)NULL, &flags);
if (error)
return error;
@ -461,8 +458,7 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
*/
do {
rcvflg = MSG_WAITALL;
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, (struct sockaddr **)NULL,
error = soreceive(so, (struct sockaddr **)NULL,
&auio, &tm, (struct mbuf **)NULL, &rcvflg);
} while (error == EWOULDBLOCK || error == EINTR ||
error == ERESTART);

View File

@ -606,8 +606,7 @@ nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
else
flags = 0;
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
flags, curthread /*XXX*/);
error = sosend(so, sendnam, 0, top, 0, flags, curthread /*XXX*/);
if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
error = 0;
mtx_lock(&rep->r_mtx);
@ -946,9 +945,8 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
auio.uio_iovcnt = 0;
mp = NULL;
rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, (struct sockaddr **)0,
&auio, &mp, (struct mbuf **)0, &rcvflg);
error = soreceive(so, (struct sockaddr **)0, &auio,
&mp, (struct mbuf **)0, &rcvflg);
/*
* We've already tested that the socket is readable. 2 cases
* here, we either read 0 bytes (client closed connection),
@ -1016,9 +1014,8 @@ nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
auio.uio_iovcnt = 0;
mp = NULL;
rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, (struct sockaddr **)0,
&auio, &mp, (struct mbuf **)0, &rcvflg);
error = soreceive(so, (struct sockaddr **)0, &auio,
&mp, (struct mbuf **)0, &rcvflg);
if (error || auio.uio_resid > 0) {
if (error && error != ECONNRESET) {
log(LOG_ERR,
@ -1058,9 +1055,7 @@ nfs_clnt_udp_soupcall(struct socket *so, void *arg, int waitflag)
auio.uio_resid = 1000000000;
do {
mp = control = NULL;
error = so->so_proto->pr_usrreqs->pru_soreceive(so,
NULL, &auio, &mp,
&control, &rcvflag);
error = soreceive(so, NULL, &auio, &mp, &control, &rcvflag);
if (control)
m_freem(control);
if (mp)

View File

@ -466,8 +466,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag)
auio.uio_resid = 1000000000;
flags = MSG_DONTWAIT;
NFSD_UNLOCK();
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, &nam, &auio, &mp, NULL, &flags);
error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
NFSD_LOCK();
if (error || mp == NULL) {
if (error == EWOULDBLOCK)
@ -503,8 +502,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag)
auio.uio_resid = 1000000000;
flags = MSG_DONTWAIT;
NFSD_UNLOCK();
error = so->so_proto->pr_usrreqs->pru_soreceive
(so, &nam, &auio, &mp, NULL, &flags);
error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
if (mp) {
struct nfsrv_rec *rec;
rec = malloc(sizeof(struct nfsrv_rec),
@ -785,8 +783,7 @@ nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top)
else
flags = 0;
error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0,
flags, curthread/*XXX*/);
error = sosend(so, sendnam, 0, top, 0, flags, curthread/*XXX*/);
if (error == ENOBUFS && so->so_type == SOCK_DGRAM)
error = 0;

View File

@ -228,15 +228,6 @@ struct pr_usrreqs {
int (*pru_sense)(struct socket *so, struct stat *sb);
int (*pru_shutdown)(struct socket *so);
int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam);
/*
* These four added later, so they are out of order. They are used
* for shortcutting (fast path input/output) in some protocols.
* XXX - that's a lie, they are not implemented yet
* Rather than calling sosend() etc. directly, calls are made
* through these entry points. For protocols which still use
* the generic code, these just point to those routines.
*/
int (*pru_sosend)(struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top, struct mbuf *control,
int flags, struct thread *td);

View File

@ -530,8 +530,13 @@ int soopt_mcopyout(struct sockopt *sopt, struct mbuf *m);
int sopoll(struct socket *so, int events, struct ucred *active_cred,
struct thread *td);
int sopoll_generic(struct socket *so, int events,
struct ucred *active_cred, struct thread *td);
int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
struct mbuf **mp0, struct mbuf **controlp, int *flagsp);
int soreceive_generic(struct socket *so, struct sockaddr **paddr,
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
int *flagsp);
int soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
void sorflush(struct socket *so);
int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
@ -540,6 +545,9 @@ int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
int sosend_dgram(struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top, struct mbuf *control,
int flags, struct thread *td);
int sosend_generic(struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top, struct mbuf *control,
int flags, struct thread *td);
int sosetopt(struct socket *so, struct sockopt *sopt);
int soshutdown(struct socket *so, int how);
void sotoxsocket(struct socket *so, struct xsocket *xso);