PERFORCE change 44227 for review
Sam Leffler
sam at FreeBSD.org
Mon Dec 22 21:25:05 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=44227
Change 44227 by sam at sam_ebb on 2003/12/22 21:24:29
Fix braino: we can drop the mutex because we have the sockbuf
marked locked (via sblock). This means the previous change to
move the externalization of MT_CONTROL mbufs doesn't need to be
moved to the bottom of soreceive--we can do it in the same place
it was before by just dropping the sockbuf lock. This means we
don't change the order of processing and so don't change any of
the semantics of error handling.
With this re-realization we can also fix the calls to dup sockaddr's
and copy data when peeking to use M_WAITOK/M_TRYWAIT. It may not
be worthwhile for performance reasons as doing so requires that we
drop+reaquire the sockbuf mutex but we can revisit that. At the
least the peek case is unlikely to be noticed and the cost is
probably down in the noice for recvfrom/recvmsg too.
Need to move local variable decls back up to the top of the
function before committing to keep bde happy.
Affected files ...
.. //depot/projects/netperf+sockets/sys/kern/uipc_socket.c#9 edit
Differences ...
==== //depot/projects/netperf+sockets/sys/kern/uipc_socket.c#9 (text+ko) ====
@@ -775,19 +775,14 @@
int flags, len, error, offset;
struct protosw *pr = so->so_proto;
struct mbuf *nextrecord;
- struct mbuf *cm, **cme;
int moff, type = 0;
int orig_resid = uio->uio_resid;
mp = mp0;
if (psa)
*psa = 0;
- cm = NULL;
- if (controlp) {
+ if (controlp)
*controlp = 0;
- cme = &cm;
- } else
- cme = &cm; /* XXX to silence gcc */
if (flagsp)
flags = *flagsp &~ MSG_EOR;
else
@@ -908,12 +903,10 @@
KASSERT(m->m_type == MT_SONAME,
("m->m_type == %d", m->m_type));
if (psa) {
+ SOCKBUF_UNLOCK(&so->so_rcv);
*psa = sodupsockaddr(mtod(m, struct sockaddr *),
- M_NOWAIT); /* XXX */
- if (*psa == NULL) {
- error = ENOMEM;
- goto release;
- }
+ M_WAITOK);
+ SOCKBUF_LOCK(&so->so_rcv);
}
if (flags & MSG_PEEK) {
m = m->m_next;
@@ -925,10 +918,16 @@
orig_resid = 0;
}
if (m && m->m_type == MT_CONTROL) {
+ struct mbuf *cm = NULL;
+ struct mbuf **cme = &cm;
+
do {
if (flags & MSG_PEEK) {
if (controlp) {
- *controlp = m_copy(m, 0, m->m_len);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ *controlp = m_copym(m, 0, m->m_len,
+ M_TRYWAIT);
+ SOCKBUF_LOCK(&so->so_rcv);
if (*controlp == NULL) {
error = ENOBUFS;
goto release;
@@ -942,10 +941,7 @@
m->m_next = NULL;
if (controlp) {
/*
- * Link mbufs together for processing
- * below. See the comments there for
- * an explanation of why we delay the
- * work.
+ * Collect mbufs for processing below.
*/
*cme = m;
cme = &(*cme)->m_next;
@@ -954,6 +950,20 @@
m = so->so_rcv.sb_mb;
}
} while (m && m->m_type == MT_CONTROL);
+ if (cm != NULL) {
+ if (pr->pr_domain->dom_externalize) {
+ /*
+ * NB: drop the lock to avoid potential LORs;
+ * in particular unix domain sockets grab the
+ * file descriptor lock which would be a LOR.
+ */
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ error = (*pr->pr_domain->dom_externalize)
+ (cm, controlp);
+ SOCKBUF_LOCK(&so->so_rcv);
+ } else
+ m_freem(cm);
+ }
orig_resid = 0;
}
if (m) {
@@ -1159,20 +1169,6 @@
sbunlock(&so->so_rcv);
out:
SOCKBUF_UNLOCK(&so->so_rcv);
- if (cm != NULL) {
- /*
- * Deal with control data now that we've dopped the
- * sockbuf lock. This is important as otherwise, for
- * unix domain sockets, we create a LOR between so_rcv
- * and the file descriptor lock. Note we assume the
- * externalize method handles a list of mbufs.
- */
- if (error == 0 && pr->pr_domain->dom_externalize) {
- /* XXX ignore error? */
- error = (*pr->pr_domain->dom_externalize)(cm, controlp);
- } else
- m_freem(cm);
- }
return (error);
}
More information about the p4-projects
mailing list