Page MenuHomeFreeBSD

D26297.id76543.diff
No OneTemporary

D26297.id76543.diff

Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c
+++ sys/kern/uipc_usrreq.c
@@ -334,6 +334,15 @@
return (ret);
}
+static void
+unp_pcb_rele_notlast(struct unpcb *unp)
+{
+ bool ret __unused;
+
+ ret = refcount_release(&unp->unp_refcount);
+ KASSERT(!ret, ("%s: unpcb %p has no references", __func__, unp));
+}
+
static void
unp_pcb_lock_pair(struct unpcb *unp, struct unpcb *unp2)
{
@@ -712,18 +721,14 @@
unp->unp_vnode = NULL;
}
unp2 = unp->unp_conn;
- unp_pcb_hold(unp);
if (__predict_false(unp == unp2)) {
unp_disconnect(unp, unp2);
} else if (unp2 != NULL) {
- unp_pcb_hold(unp2);
unp_pcb_owned_lock2(unp, unp2, freed);
unp_disconnect(unp, unp2);
- if (unp_pcb_rele(unp2) == 0)
- UNP_PCB_UNLOCK(unp2);
- }
- if (unp_pcb_rele(unp) == 0)
+ } else {
UNP_PCB_UNLOCK(unp);
+ }
if (vp) {
mtx_unlock(vplock);
vrele(vp);
@@ -810,14 +815,11 @@
unp2 = NULL;
}
unp_pcb_hold(unp);
- if (unp2 != NULL) {
- unp_pcb_hold(unp2);
+ if (unp2 != NULL)
unp_disconnect(unp, unp2);
- if (unp_pcb_rele(unp2) == 0)
- UNP_PCB_UNLOCK(unp2);
- }
+ else
+ UNP_PCB_UNLOCK(unp);
}
- UNP_PCB_UNLOCK(unp);
UNP_REF_LIST_LOCK();
while (!LIST_EMPTY(&unp->unp_refs)) {
struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
@@ -870,14 +872,8 @@
UNP_PCB_UNLOCK(unp);
return (0);
}
- unp_pcb_hold(unp2);
}
- unp_pcb_hold(unp);
unp_disconnect(unp, unp2);
- if (unp_pcb_rele(unp) == 0)
- UNP_PCB_UNLOCK(unp);
- if ((unp != unp2) && unp_pcb_rele(unp2) == 0)
- UNP_PCB_UNLOCK(unp2);
return (0);
}
@@ -1114,11 +1110,13 @@
SOCKBUF_UNLOCK(&so2->so_rcv);
error = ENOBUFS;
}
- if (nam != NULL)
+ if (nam != NULL) {
unp_disconnect(unp, unp2);
- if (__predict_true(unp != unp2))
- UNP_PCB_UNLOCK(unp2);
- UNP_PCB_UNLOCK(unp);
+ } else {
+ if (__predict_true(unp != unp2))
+ UNP_PCB_UNLOCK(unp2);
+ UNP_PCB_UNLOCK(unp);
+ }
break;
}
@@ -1752,23 +1750,29 @@
unp_disconnect(struct unpcb *unp, struct unpcb *unp2)
{
struct socket *so, *so2;
- int freed __unused;
-
- KASSERT(unp2 != NULL, ("unp_disconnect: unp2 == NULL"));
+#ifdef INVARIANTS
+ struct unpcb *unptmp;
+#endif
UNP_PCB_LOCK_ASSERT(unp);
UNP_PCB_LOCK_ASSERT(unp2);
+ KASSERT(unp->unp_conn == unp2,
+ ("%s: unpcb %p is not connected to %p", __func__, unp, unp2));
- if (unp->unp_conn == NULL && unp2->unp_conn == NULL)
- return;
-
- MPASS(unp->unp_conn == unp2);
unp->unp_conn = NULL;
so = unp->unp_socket;
so2 = unp2->unp_socket;
switch (unp->unp_socket->so_type) {
case SOCK_DGRAM:
UNP_REF_LIST_LOCK();
+#ifdef INVARIANTS
+ LIST_FOREACH(unptmp, &unp2->unp_refs, unp_reflink) {
+ if (unptmp == unp)
+ break;
+ }
+ KASSERT(unptmp != NULL,
+ ("%s: %p not found in reflist of %p", __func__, unp, unp2));
+#endif
LIST_REMOVE(unp, unp_reflink);
UNP_REF_LIST_UNLOCK();
if (so) {
@@ -1788,10 +1792,17 @@
soisdisconnected(so2);
break;
}
- freed = unp_pcb_rele(unp);
- MPASS(freed == 0);
- freed = unp_pcb_rele(unp2);
- MPASS(freed == 0);
+
+ if (unp == unp2) {
+ unp_pcb_rele_notlast(unp);
+ if (!unp_pcb_rele(unp))
+ UNP_PCB_UNLOCK(unp);
+ } else {
+ if (!unp_pcb_rele(unp))
+ UNP_PCB_UNLOCK(unp);
+ if (!unp_pcb_rele(unp2))
+ UNP_PCB_UNLOCK(unp2);
+ }
}
/*
@@ -1987,17 +1998,14 @@
if (so)
so->so_error = ECONNRESET;
unp2 = unp->unp_conn;
+ /* Last reference dropped in unp_disconnect(). */
+ unp_pcb_rele_notlast(unp);
if (unp2 == unp) {
unp_disconnect(unp, unp2);
} else if (unp2 != NULL) {
- unp_pcb_hold(unp2);
unp_pcb_owned_lock2(unp, unp2, freed);
unp_disconnect(unp, unp2);
- if (unp_pcb_rele(unp2) == 0)
- UNP_PCB_UNLOCK(unp2);
}
- if (unp_pcb_rele(unp) == 0)
- UNP_PCB_UNLOCK(unp);
}
static void

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 25, 1:23 PM (21 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35474772
Default Alt Text
D26297.id76543.diff (3 KB)

Event Timeline