Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167712451
D58770.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D58770.diff
View Options
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -2960,6 +2960,7 @@
bcopy(path, buf, len);
buf[len] = 0;
+ so2 = NULL;
error = 0;
unp = sotounpcb(so);
@@ -2999,23 +3000,31 @@
UNP_PCB_UNLOCK(unp);
error = unp_resolve_peer(td, fd, buf, &so2);
+ if (error == 0)
+ error = unp_connect_peer(so, sotounpcb(so2), td,
+ referenced_peerp != NULL);
+
+ /*
+ * We are the ones wanting the lock, so we take it whenever a failure
+ * left us without one. A success hands ours back already held.
+ */
if (error != 0)
- goto out;
- error = unp_connect_peer(so, sotounpcb(so2), td,
- referenced_peerp != NULL);
- /* Transfer the reference; the caller releases it after unlocking. */
- if (error == 0 && referenced_peerp != NULL)
- *referenced_peerp = so2;
- else
- sorele(so2);
-out:
- if (__predict_false(error)) {
UNP_PCB_LOCK(unp);
- KASSERT((unp->unp_flags & UNP_CONNECTING) != 0,
- ("%s: unp %p has UNP_CONNECTING clear", __func__, unp));
- unp->unp_flags &= ~UNP_CONNECTING;
- UNP_PCB_UNLOCK(unp);
+ UNP_PCB_LOCK_ASSERT(unp);
+ KASSERT((unp->unp_flags & UNP_CONNECTING) != 0,
+ ("%s: unp %p has UNP_CONNECTING clear", __func__, unp));
+ unp->unp_flags &= ~UNP_CONNECTING;
+
+ if (error == 0 && referenced_peerp != NULL) {
+ /* Both PCBs stay locked, and the reference goes with them. */
+ *referenced_peerp = so2;
+ return (0);
}
+ UNP_PCB_UNLOCK(unp);
+
+ /* Only once unlocked: the last release can re-enter uipc_close(). */
+ if (so2 != NULL)
+ sorele(so2);
return (error);
}
@@ -3124,7 +3133,7 @@
/*
* Dispatch on the resolved vnode, then drop it: for the socket cases the
* returned reference keeps the peer stable, so the caller holds no vnode
- * lock across unp_connect_peer() (which matters for the return_locked
+ * lock across unp_connect_peer() (which matters for the return_peer_locked
* datagram fast path).
*
* A synthetic descriptor node -- as fdescfs fabricates for a /dev/fd/N
@@ -3194,11 +3203,14 @@
* peer socket, or the vnode lock plus unp_vp_mtxpool lock for a peer found
* via VOP_UNP_CONNECT()).
*
- * On success UNP_CONNECTING is cleared; on error the caller must clear it.
+ * On success returns with 'so's PCB lock held, so that the caller may clear
+ * UNP_CONNECTING without reacquiring it; the peer's is held as well if
+ * 'return_peer_locked', and dropped otherwise. On failure no lock is held,
+ * none having been taken.
*/
static int
unp_connect_peer(struct socket *so, struct unpcb *unp2, struct thread *td,
- bool return_locked)
+ bool return_peer_locked)
{
struct socket *so2;
struct sockaddr *sa;
@@ -3262,11 +3274,8 @@
unp_connect2(so, so2, connreq);
if (connreq)
(void)solisten_enqueue(so2, SS_ISCONNECTED);
- KASSERT((unp->unp_flags & UNP_CONNECTING) != 0,
- ("%s: unp %p has UNP_CONNECTING clear", __func__, unp));
- unp->unp_flags &= ~UNP_CONNECTING;
- if (!return_locked)
- unp_pcb_unlock_pair(unp, unp2);
+ if (!return_peer_locked && unp != unp2)
+ UNP_PCB_UNLOCK(unp2);
free(sa, M_SONAME);
return (0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Aug 24, 10:27 PM (15 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36529202
Default Alt Text
D58770.diff (3 KB)
Attached To
Mode
D58770: unix: set and clear UNP_CONNECTING in the same function
Attached
Detach File
Event Timeline
Log In to Comment