summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_sockbuf.c3
-rw-r--r--sys/kern/uipc_socket.c24
-rw-r--r--sys/sys/socketvar.h1
3 files changed, 14 insertions, 14 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 16923cf..9e89826 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -67,7 +67,6 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */
static void sbdrop_internal(struct sockbuf *sb, int len);
static void sbflush_internal(struct sockbuf *sb);
-static void sbrelease_internal(struct sockbuf *sb, struct socket *so);
/*
* Socantsendmore indicates that no more data will be sent on the socket; it
@@ -322,7 +321,7 @@ sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
/*
* Free mbufs held by a socket, and reserved mbuf space.
*/
-static void
+void
sbrelease_internal(struct sockbuf *sb, struct socket *so)
{
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 0de6d29..bbb4f89 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1877,15 +1877,13 @@ sorflush(struct socket *so)
struct sockbuf asb;
/*
- * XXXRW: This is quite ugly. Previously, this code made a copy of
- * the socket buffer, then zero'd the original to clear the buffer
- * fields. However, with mutexes in the socket buffer, this causes
- * problems. We only clear the zeroable bits of the original;
- * however, we have to initialize and destroy the mutex in the copy
- * so that dom_dispose() and sbrelease() can lock t as needed.
- */
-
- /*
+ * In order to avoid calling dom_dispose with the socket buffer mutex
+ * held, and in order to generally avoid holding the lock for a long
+ * time, we make a copy of the socket buffer and clear the original
+ * (except locks, state). The new socket buffer copy won't have
+ * initialized locks so we can only call routines that won't use or
+ * assert those locks.
+ *
* Dislodge threads currently blocked in receive and wait to acquire
* a lock against other simultaneous readers before clearing the
* socket buffer. Don't let our acquire be interrupted by a signal
@@ -1907,11 +1905,13 @@ sorflush(struct socket *so)
SOCKBUF_UNLOCK(sb);
sbunlock(sb);
- SOCKBUF_LOCK_INIT(&asb, "so_rcv");
+ /*
+ * Dispose of special rights and flush the socket buffer. Don't call
+ * any unsafe routines (that rely on locks being initialized) on asb.
+ */
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
(*pr->pr_domain->dom_dispose)(asb.sb_mb);
- sbrelease(&asb, so);
- SOCKBUF_LOCK_DESTROY(&asb);
+ sbrelease_internal(&asb, so);
}
/*
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 09e58ab..40f3dd9 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -483,6 +483,7 @@ void sbdroprecord_locked(struct sockbuf *sb);
void sbflush(struct sockbuf *sb);
void sbflush_locked(struct sockbuf *sb);
void sbrelease(struct sockbuf *sb, struct socket *so);
+void sbrelease_internal(struct sockbuf *sb, struct socket *so);
void sbrelease_locked(struct sockbuf *sb, struct socket *so);
int sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
struct thread *td);
OpenPOWER on IntegriCloud