aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Macy <mmacy@FreeBSD.org>2018-05-24 21:13:46 +0000
committerMatt Macy <mmacy@FreeBSD.org>2018-05-24 21:13:46 +0000
commitacf9fd05d83c72b5e5f55c032d28676f3641a01a (patch)
treeee133217b75aa50aa279021ccb6daf9567f0b0ae
parent509b94387ab8011705b31e805cdb57e89e7ad72b (diff)
Notes
-rw-r--r--sys/kern/uipc_usrreq.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 363bc4fb75cf..b47d066c9242 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -722,7 +722,9 @@ uipc_close(struct socket *so)
}
unp2 = unp->unp_conn;
unp_pcb_hold(unp);
- if (unp2 != NULL) {
+ 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);
@@ -747,9 +749,13 @@ uipc_connect2(struct socket *so1, struct socket *so2)
KASSERT(unp != NULL, ("uipc_connect2: unp == NULL"));
unp2 = so2->so_pcb;
KASSERT(unp2 != NULL, ("uipc_connect2: unp2 == NULL"));
- unp_pcb_lock2(unp, unp2);
+ if (unp != unp2)
+ unp_pcb_lock2(unp, unp2);
+ else
+ UNP_PCB_LOCK(unp);
error = unp_connect2(so1, so2, PRU_CONNECT2);
- UNP_PCB_UNLOCK(unp2);
+ if (unp != unp2)
+ UNP_PCB_UNLOCK(unp2);
UNP_PCB_UNLOCK(unp);
return (error);
}
@@ -783,29 +789,30 @@ uipc_detach(struct socket *so)
mtx_lock(vplock);
}
UNP_PCB_LOCK(unp);
- if ((unp2 = unp->unp_conn) != NULL) {
- unp_pcb_owned_lock2(unp, unp2, freeunp);
- if (freeunp)
- unp2 = NULL;
- }
if (unp->unp_vnode != vp &&
unp->unp_vnode != NULL) {
if (vplock)
mtx_unlock(vplock);
UNP_PCB_UNLOCK(unp);
- if (unp2)
- UNP_PCB_UNLOCK(unp2);
goto restart;
}
if ((unp->unp_flags & UNP_NASCENT) != 0) {
- if (unp2)
- UNP_PCB_UNLOCK(unp2);
goto teardown;
}
if ((vp = unp->unp_vnode) != NULL) {
VOP_UNP_DETACH(vp);
unp->unp_vnode = NULL;
}
+ if (__predict_false(unp == unp->unp_conn)) {
+ unp_disconnect(unp, unp);
+ unp2 = NULL;
+ goto connect_self;
+ }
+ if ((unp2 = unp->unp_conn) != NULL) {
+ unp_pcb_owned_lock2(unp, unp2, freeunp);
+ if (freeunp)
+ unp2 = NULL;
+ }
unp_pcb_hold(unp);
if (unp2 != NULL) {
unp_pcb_hold(unp2);
@@ -813,6 +820,7 @@ uipc_detach(struct socket *so)
if (unp_pcb_rele(unp2) == 0)
UNP_PCB_UNLOCK(unp2);
}
+ connect_self:
UNP_PCB_UNLOCK(unp);
UNP_REF_LIST_LOCK();
while (!LIST_EMPTY(&unp->unp_refs)) {
@@ -864,6 +872,10 @@ uipc_disconnect(struct socket *so)
UNP_PCB_UNLOCK(unp);
return (0);
}
+ if (unp == unp2) {
+ if (unp_pcb_rele(unp) == 0)
+ UNP_PCB_UNLOCK(unp);
+ }
unp_pcb_owned_lock2(unp, unp2, freed);
if (__predict_false(freed)) {
UNP_PCB_UNLOCK(unp);
@@ -1925,7 +1937,9 @@ unp_drop(struct unpcb *unp)
if (so)
so->so_error = ECONNRESET;
unp2 = unp->unp_conn;
- if (unp2 != NULL) {
+ 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);