Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_usrreq.c
Show First 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | uipc_attach(struct socket *so, int proto, struct thread *td) | ||||
unp = uma_zalloc(unp_zone, M_NOWAIT | M_ZERO); | unp = uma_zalloc(unp_zone, M_NOWAIT | M_ZERO); | ||||
if (unp == NULL) | if (unp == NULL) | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
LIST_INIT(&unp->unp_refs); | LIST_INIT(&unp->unp_refs); | ||||
UNP_PCB_LOCK_INIT(unp); | UNP_PCB_LOCK_INIT(unp); | ||||
unp->unp_socket = so; | unp->unp_socket = so; | ||||
so->so_pcb = unp; | so->so_pcb = unp; | ||||
unp->unp_refcount = 1; | unp->unp_refcount = 1; | ||||
if (so->so_head != NULL) | if (so->so_listen != NULL) | ||||
unp->unp_flags |= UNP_NASCENT; | unp->unp_flags |= UNP_NASCENT; | ||||
UNP_LIST_LOCK(); | UNP_LIST_LOCK(); | ||||
unp->unp_gencnt = ++unp_gencnt; | unp->unp_gencnt = ++unp_gencnt; | ||||
unp_count++; | unp_count++; | ||||
switch (so->so_type) { | switch (so->so_type) { | ||||
case SOCK_STREAM: | case SOCK_STREAM: | ||||
LIST_INSERT_HEAD(&unp_shead, unp, unp_link); | LIST_INSERT_HEAD(&unp_shead, unp, unp_link); | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | if (error) { | ||||
goto error; | goto error; | ||||
} | } | ||||
vp = nd.ni_vp; | vp = nd.ni_vp; | ||||
ASSERT_VOP_ELOCKED(vp, "uipc_bind"); | ASSERT_VOP_ELOCKED(vp, "uipc_bind"); | ||||
soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK); | soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK); | ||||
UNP_LINK_WLOCK(); | UNP_LINK_WLOCK(); | ||||
UNP_PCB_LOCK(unp); | UNP_PCB_LOCK(unp); | ||||
VOP_UNP_BIND(vp, unp->unp_socket); | VOP_UNP_BIND(vp, unp); | ||||
unp->unp_vnode = vp; | unp->unp_vnode = vp; | ||||
unp->unp_addr = soun; | unp->unp_addr = soun; | ||||
unp->unp_flags &= ~UNP_BINDING; | unp->unp_flags &= ~UNP_BINDING; | ||||
UNP_PCB_UNLOCK(unp); | UNP_PCB_UNLOCK(unp); | ||||
UNP_LINK_WUNLOCK(); | UNP_LINK_WUNLOCK(); | ||||
VOP_UNLOCK(vp, 0); | VOP_UNLOCK(vp, 0); | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
free(buf, M_TEMP); | free(buf, M_TEMP); | ||||
Show All 38 Lines | uipc_connectat(int fd, struct socket *so, struct sockaddr *nam, | ||||
UNP_LINK_WUNLOCK(); | UNP_LINK_WUNLOCK(); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
uipc_close(struct socket *so) | uipc_close(struct socket *so) | ||||
{ | { | ||||
struct unpcb *unp, *unp2; | struct unpcb *unp, *unp2; | ||||
struct vnode *vp = NULL; | |||||
unp = sotounpcb(so); | unp = sotounpcb(so); | ||||
KASSERT(unp != NULL, ("uipc_close: unp == NULL")); | KASSERT(unp != NULL, ("uipc_close: unp == NULL")); | ||||
UNP_LINK_WLOCK(); | UNP_LINK_WLOCK(); | ||||
UNP_PCB_LOCK(unp); | UNP_PCB_LOCK(unp); | ||||
unp2 = unp->unp_conn; | unp2 = unp->unp_conn; | ||||
if (unp2 != NULL) { | if (unp2 != NULL) { | ||||
UNP_PCB_LOCK(unp2); | UNP_PCB_LOCK(unp2); | ||||
unp_disconnect(unp, unp2); | unp_disconnect(unp, unp2); | ||||
UNP_PCB_UNLOCK(unp2); | UNP_PCB_UNLOCK(unp2); | ||||
} | } | ||||
if (SOLISTENING(so) && ((vp = unp->unp_vnode) != NULL)) { | |||||
VOP_UNP_DETACH(vp); | |||||
unp->unp_vnode = NULL; | |||||
} | |||||
UNP_PCB_UNLOCK(unp); | UNP_PCB_UNLOCK(unp); | ||||
UNP_LINK_WUNLOCK(); | UNP_LINK_WUNLOCK(); | ||||
if (vp) | |||||
vrele(vp); | |||||
} | } | ||||
static int | static int | ||||
uipc_connect2(struct socket *so1, struct socket *so2) | uipc_connect2(struct socket *so1, struct socket *so2) | ||||
{ | { | ||||
struct unpcb *unp, *unp2; | struct unpcb *unp, *unp2; | ||||
int error; | int error; | ||||
Show All 26 Lines | uipc_detach(struct socket *so) | ||||
local_unp_rights = 0; | local_unp_rights = 0; | ||||
UNP_LIST_LOCK(); | UNP_LIST_LOCK(); | ||||
LIST_REMOVE(unp, unp_link); | LIST_REMOVE(unp, unp_link); | ||||
unp->unp_gencnt = ++unp_gencnt; | unp->unp_gencnt = ++unp_gencnt; | ||||
--unp_count; | --unp_count; | ||||
UNP_LIST_UNLOCK(); | UNP_LIST_UNLOCK(); | ||||
if ((unp->unp_flags & UNP_NASCENT) != 0) { | |||||
UNP_PCB_LOCK(unp); | |||||
goto teardown; | |||||
} | |||||
UNP_LINK_WLOCK(); | UNP_LINK_WLOCK(); | ||||
UNP_PCB_LOCK(unp); | UNP_PCB_LOCK(unp); | ||||
if ((unp->unp_flags & UNP_NASCENT) != 0) | |||||
goto teardown; | |||||
/* | |||||
* XXXRW: Should assert vp->v_socket == so. | |||||
*/ | |||||
if ((vp = unp->unp_vnode) != NULL) { | if ((vp = unp->unp_vnode) != NULL) { | ||||
VOP_UNP_DETACH(vp); | VOP_UNP_DETACH(vp); | ||||
unp->unp_vnode = NULL; | unp->unp_vnode = NULL; | ||||
} | } | ||||
unp2 = unp->unp_conn; | unp2 = unp->unp_conn; | ||||
if (unp2 != NULL) { | if (unp2 != NULL) { | ||||
UNP_PCB_LOCK(unp2); | UNP_PCB_LOCK(unp2); | ||||
unp_disconnect(unp, unp2); | unp_disconnect(unp, unp2); | ||||
UNP_PCB_UNLOCK(unp2); | UNP_PCB_UNLOCK(unp2); | ||||
} | } | ||||
/* | /* | ||||
* We hold the linkage lock exclusively, so it's OK to acquire | * We hold the linkage lock exclusively, so it's OK to acquire | ||||
* multiple pcb locks at a time. | * multiple pcb locks at a time. | ||||
*/ | */ | ||||
while (!LIST_EMPTY(&unp->unp_refs)) { | while (!LIST_EMPTY(&unp->unp_refs)) { | ||||
struct unpcb *ref = LIST_FIRST(&unp->unp_refs); | struct unpcb *ref = LIST_FIRST(&unp->unp_refs); | ||||
UNP_PCB_LOCK(ref); | UNP_PCB_LOCK(ref); | ||||
unp_drop(ref); | unp_drop(ref); | ||||
UNP_PCB_UNLOCK(ref); | UNP_PCB_UNLOCK(ref); | ||||
} | } | ||||
local_unp_rights = unp_rights; | local_unp_rights = unp_rights; | ||||
UNP_LINK_WUNLOCK(); | |||||
teardown: | teardown: | ||||
UNP_LINK_WUNLOCK(); | |||||
unp->unp_socket->so_pcb = NULL; | unp->unp_socket->so_pcb = NULL; | ||||
saved_unp_addr = unp->unp_addr; | saved_unp_addr = unp->unp_addr; | ||||
unp->unp_addr = NULL; | unp->unp_addr = NULL; | ||||
unp->unp_refcount--; | unp->unp_refcount--; | ||||
freeunp = (unp->unp_refcount == 0); | freeunp = (unp->unp_refcount == 0); | ||||
if (saved_unp_addr != NULL) | if (saved_unp_addr != NULL) | ||||
free(saved_unp_addr, M_SONAME); | free(saved_unp_addr, M_SONAME); | ||||
if (freeunp) { | if (freeunp) { | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (unp->unp_vnode == NULL) { | ||||
UNP_PCB_UNLOCK(unp); | UNP_PCB_UNLOCK(unp); | ||||
return (error); | return (error); | ||||
} | } | ||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
error = solisten_proto_check(so); | error = solisten_proto_check(so); | ||||
if (error == 0) { | if (error == 0) { | ||||
cru2x(td->td_ucred, &unp->unp_peercred); | cru2x(td->td_ucred, &unp->unp_peercred); | ||||
unp->unp_flags |= UNP_HAVEPCCACHED; | |||||
solisten_proto(so, backlog); | solisten_proto(so, backlog); | ||||
} | } | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
UNP_PCB_UNLOCK(unp); | UNP_PCB_UNLOCK(unp); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 541 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
unp_connectat(int fd, struct socket *so, struct sockaddr *nam, | unp_connectat(int fd, struct socket *so, struct sockaddr *nam, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
struct sockaddr_un *soun = (struct sockaddr_un *)nam; | struct sockaddr_un *soun = (struct sockaddr_un *)nam; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct socket *so2, *so3; | struct socket *so2; | ||||
struct unpcb *unp, *unp2, *unp3; | struct unpcb *unp, *unp2, *unp3; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
char buf[SOCK_MAXADDRLEN]; | char buf[SOCK_MAXADDRLEN]; | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int error, len; | int error, len; | ||||
if (nam->sa_family != AF_UNIX) | if (nam->sa_family != AF_UNIX) | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | #endif | ||||
unp = sotounpcb(so); | unp = sotounpcb(so); | ||||
KASSERT(unp != NULL, ("unp_connect: unp == NULL")); | KASSERT(unp != NULL, ("unp_connect: unp == NULL")); | ||||
/* | /* | ||||
* Lock linkage lock for two reasons: make sure v_socket is stable, | * Lock linkage lock for two reasons: make sure v_socket is stable, | ||||
* and to protect simultaneous locking of multiple pcbs. | * and to protect simultaneous locking of multiple pcbs. | ||||
*/ | */ | ||||
UNP_LINK_WLOCK(); | UNP_LINK_WLOCK(); | ||||
VOP_UNP_CONNECT(vp, &so2); | VOP_UNP_CONNECT(vp, &unp2); | ||||
if (so2 == NULL) { | if (unp2 == NULL) { | ||||
error = ECONNREFUSED; | error = ECONNREFUSED; | ||||
goto bad2; | goto bad2; | ||||
} | } | ||||
so2 = unp2->unp_socket; | |||||
if (so->so_type != so2->so_type) { | if (so->so_type != so2->so_type) { | ||||
error = EPROTOTYPE; | error = EPROTOTYPE; | ||||
goto bad2; | goto bad2; | ||||
} | } | ||||
UNP_PCB_LOCK(unp); | |||||
UNP_PCB_LOCK(unp2); | |||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) { | if (so->so_proto->pr_flags & PR_CONNREQUIRED) { | ||||
if (so2->so_options & SO_ACCEPTCONN) { | if (so2->so_options & SO_ACCEPTCONN) { | ||||
CURVNET_SET(so2->so_vnet); | CURVNET_SET(so2->so_vnet); | ||||
so3 = sonewconn(so2, 0); | so2 = sonewconn(so2, 0); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} else | } else | ||||
so3 = NULL; | so2 = NULL; | ||||
if (so3 == NULL) { | if (so2 == NULL) { | ||||
error = ECONNREFUSED; | error = ECONNREFUSED; | ||||
goto bad2; | goto bad3; | ||||
} | } | ||||
unp = sotounpcb(so); | unp3 = sotounpcb(so2); | ||||
unp2 = sotounpcb(so2); | |||||
unp3 = sotounpcb(so3); | |||||
UNP_PCB_LOCK(unp); | |||||
UNP_PCB_LOCK(unp2); | |||||
UNP_PCB_LOCK(unp3); | UNP_PCB_LOCK(unp3); | ||||
if (unp2->unp_addr != NULL) { | if (unp2->unp_addr != NULL) { | ||||
bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len); | bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len); | ||||
unp3->unp_addr = (struct sockaddr_un *) sa; | unp3->unp_addr = (struct sockaddr_un *) sa; | ||||
sa = NULL; | sa = NULL; | ||||
} | } | ||||
/* | /* | ||||
* The connector's (client's) credentials are copied from its | * The connector's (client's) credentials are copied from its | ||||
* process structure at the time of connect() (which is now). | * process structure at the time of connect() (which is now). | ||||
*/ | */ | ||||
cru2x(td->td_ucred, &unp3->unp_peercred); | cru2x(td->td_ucred, &unp3->unp_peercred); | ||||
unp3->unp_flags |= UNP_HAVEPC; | unp3->unp_flags |= UNP_HAVEPC; | ||||
/* | /* | ||||
* The receiver's (server's) credentials are copied from the | * The receiver's (server's) credentials are copied from the | ||||
* unp_peercred member of socket on which the former called | * unp_peercred member of socket on which the former called | ||||
* listen(); uipc_listen() cached that process's credentials | * listen(); uipc_listen() cached that process's credentials | ||||
* at that time so we can use them now. | * at that time so we can use them now. | ||||
*/ | */ | ||||
KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED, | |||||
("unp_connect: listener without cached peercred")); | |||||
memcpy(&unp->unp_peercred, &unp2->unp_peercred, | memcpy(&unp->unp_peercred, &unp2->unp_peercred, | ||||
sizeof(unp->unp_peercred)); | sizeof(unp->unp_peercred)); | ||||
unp->unp_flags |= UNP_HAVEPC; | unp->unp_flags |= UNP_HAVEPC; | ||||
if (unp2->unp_flags & UNP_WANTCRED) | if (unp2->unp_flags & UNP_WANTCRED) | ||||
unp3->unp_flags |= UNP_WANTCRED; | unp3->unp_flags |= UNP_WANTCRED; | ||||
UNP_PCB_UNLOCK(unp3); | |||||
UNP_PCB_UNLOCK(unp2); | UNP_PCB_UNLOCK(unp2); | ||||
UNP_PCB_UNLOCK(unp); | unp2 = unp3; | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_socketpeer_set_from_socket(so, so3); | mac_socketpeer_set_from_socket(so, so2); | ||||
mac_socketpeer_set_from_socket(so3, so); | mac_socketpeer_set_from_socket(so2, so); | ||||
#endif | #endif | ||||
so2 = so3; | |||||
} | } | ||||
unp = sotounpcb(so); | |||||
KASSERT(unp != NULL, ("unp_connect: unp == NULL")); | KASSERT(unp2 != NULL && so2 != NULL && unp2->unp_socket == so2 && | ||||
unp2 = sotounpcb(so2); | sotounpcb(so2) == unp2, | ||||
KASSERT(unp2 != NULL, ("unp_connect: unp2 == NULL")); | ("%s: unp2 %p so2 %p", __func__, unp2, so2)); | ||||
UNP_PCB_LOCK(unp); | |||||
UNP_PCB_LOCK(unp2); | |||||
error = unp_connect2(so, so2, PRU_CONNECT); | error = unp_connect2(so, so2, PRU_CONNECT); | ||||
bad3: | |||||
UNP_PCB_UNLOCK(unp2); | UNP_PCB_UNLOCK(unp2); | ||||
UNP_PCB_UNLOCK(unp); | UNP_PCB_UNLOCK(unp); | ||||
bad2: | bad2: | ||||
UNP_LINK_WUNLOCK(); | UNP_LINK_WUNLOCK(); | ||||
bad: | bad: | ||||
if (vp != NULL) | if (vp != NULL) | ||||
vput(vp); | vput(vp); | ||||
free(sa, M_SONAME); | free(sa, M_SONAME); | ||||
▲ Show 20 Lines • Show All 766 Lines • ▼ Show 20 Lines | for (i = 0; i < fdcount; i++) { | ||||
unp->unp_gcflag |= UNPGC_REF; | unp->unp_gcflag |= UNPGC_REF; | ||||
unp_marked++; | unp_marked++; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
unp_gc_process(struct unpcb *unp) | unp_gc_process(struct unpcb *unp) | ||||
{ | { | ||||
struct socket *soa; | struct socket *so, *soa; | ||||
struct socket *so; | |||||
struct file *fp; | struct file *fp; | ||||
/* Already processed. */ | /* Already processed. */ | ||||
if (unp->unp_gcflag & UNPGC_SCANNED) | if (unp->unp_gcflag & UNPGC_SCANNED) | ||||
return; | return; | ||||
fp = unp->unp_file; | fp = unp->unp_file; | ||||
/* | /* | ||||
* Check for a socket potentially in a cycle. It must be in a | * Check for a socket potentially in a cycle. It must be in a | ||||
* queue as indicated by msgcount, and this must equal the file | * queue as indicated by msgcount, and this must equal the file | ||||
* reference count. Note that when msgcount is 0 the file is NULL. | * reference count. Note that when msgcount is 0 the file is NULL. | ||||
*/ | */ | ||||
if ((unp->unp_gcflag & UNPGC_REF) == 0 && fp && | if ((unp->unp_gcflag & UNPGC_REF) == 0 && fp && | ||||
unp->unp_msgcount != 0 && fp->f_count == unp->unp_msgcount) { | unp->unp_msgcount != 0 && fp->f_count == unp->unp_msgcount) { | ||||
unp->unp_gcflag |= UNPGC_DEAD; | unp->unp_gcflag |= UNPGC_DEAD; | ||||
unp_unreachable++; | unp_unreachable++; | ||||
return; | return; | ||||
} | } | ||||
/* | |||||
* Mark all sockets we reference with RIGHTS. | |||||
*/ | |||||
so = unp->unp_socket; | so = unp->unp_socket; | ||||
if ((unp->unp_gcflag & UNPGC_IGNORE_RIGHTS) == 0) { | SOCK_LOCK(so); | ||||
SOCKBUF_LOCK(&so->so_rcv); | if (SOLISTENING(so)) { | ||||
unp_scan(so->so_rcv.sb_mb, unp_accessable); | |||||
SOCKBUF_UNLOCK(&so->so_rcv); | |||||
} | |||||
/* | /* | ||||
* Mark all sockets in our accept queue. | * Mark all sockets in our accept queue. | ||||
*/ | */ | ||||
ACCEPT_LOCK(); | TAILQ_FOREACH(soa, &so->sol_comp, so_list) { | ||||
TAILQ_FOREACH(soa, &so->so_comp, so_list) { | if (sotounpcb(soa)->unp_gcflag & UNPGC_IGNORE_RIGHTS) | ||||
if ((sotounpcb(soa)->unp_gcflag & UNPGC_IGNORE_RIGHTS) != 0) | |||||
continue; | continue; | ||||
SOCKBUF_LOCK(&soa->so_rcv); | SOCKBUF_LOCK(&soa->so_rcv); | ||||
unp_scan(soa->so_rcv.sb_mb, unp_accessable); | unp_scan(soa->so_rcv.sb_mb, unp_accessable); | ||||
SOCKBUF_UNLOCK(&soa->so_rcv); | SOCKBUF_UNLOCK(&soa->so_rcv); | ||||
} | } | ||||
ACCEPT_UNLOCK(); | } else { | ||||
/* | |||||
* Mark all sockets we reference with RIGHTS. | |||||
*/ | |||||
if ((unp->unp_gcflag & UNPGC_IGNORE_RIGHTS) == 0) { | |||||
SOCKBUF_LOCK(&so->so_rcv); | |||||
unp_scan(so->so_rcv.sb_mb, unp_accessable); | |||||
SOCKBUF_UNLOCK(&so->so_rcv); | |||||
} | |||||
} | |||||
SOCK_UNLOCK(so); | |||||
unp->unp_gcflag |= UNPGC_SCANNED; | unp->unp_gcflag |= UNPGC_SCANNED; | ||||
} | } | ||||
static int unp_recycled; | static int unp_recycled; | ||||
SYSCTL_INT(_net_local, OID_AUTO, recycled, CTLFLAG_RD, &unp_recycled, 0, | SYSCTL_INT(_net_local, OID_AUTO, recycled, CTLFLAG_RD, &unp_recycled, 0, | ||||
"Number of unreachable sockets claimed by the garbage collector."); | "Number of unreachable sockets claimed by the garbage collector."); | ||||
static int unp_taskcount; | static int unp_taskcount; | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
unp_dispose(struct socket *so) | unp_dispose(struct socket *so) | ||||
{ | { | ||||
struct unpcb *unp; | struct unpcb *unp; | ||||
unp = sotounpcb(so); | unp = sotounpcb(so); | ||||
UNP_LIST_LOCK(); | UNP_LIST_LOCK(); | ||||
unp->unp_gcflag |= UNPGC_IGNORE_RIGHTS; | unp->unp_gcflag |= UNPGC_IGNORE_RIGHTS; | ||||
UNP_LIST_UNLOCK(); | UNP_LIST_UNLOCK(); | ||||
if (!SOLISTENING(so)) | |||||
unp_dispose_mbuf(so->so_rcv.sb_mb); | unp_dispose_mbuf(so->so_rcv.sb_mb); | ||||
} | } | ||||
static void | static void | ||||
unp_scan(struct mbuf *m0, void (*op)(struct filedescent **, int)) | unp_scan(struct mbuf *m0, void (*op)(struct filedescent **, int)) | ||||
{ | { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
void *data; | void *data; | ||||
Show All 38 Lines | |||||
/* | /* | ||||
* A helper function called by VFS before socket-type vnode reclamation. | * A helper function called by VFS before socket-type vnode reclamation. | ||||
* For an active vnode it clears unp_vnode pointer and decrements unp_vnode | * For an active vnode it clears unp_vnode pointer and decrements unp_vnode | ||||
* use count. | * use count. | ||||
*/ | */ | ||||
void | void | ||||
vfs_unp_reclaim(struct vnode *vp) | vfs_unp_reclaim(struct vnode *vp) | ||||
{ | { | ||||
struct socket *so; | |||||
struct unpcb *unp; | struct unpcb *unp; | ||||
int active; | int active; | ||||
ASSERT_VOP_ELOCKED(vp, "vfs_unp_reclaim"); | ASSERT_VOP_ELOCKED(vp, "vfs_unp_reclaim"); | ||||
KASSERT(vp->v_type == VSOCK, | KASSERT(vp->v_type == VSOCK, | ||||
("vfs_unp_reclaim: vp->v_type != VSOCK")); | ("vfs_unp_reclaim: vp->v_type != VSOCK")); | ||||
active = 0; | active = 0; | ||||
UNP_LINK_WLOCK(); | UNP_LINK_WLOCK(); | ||||
VOP_UNP_CONNECT(vp, &so); | VOP_UNP_CONNECT(vp, &unp); | ||||
if (so == NULL) | |||||
goto done; | |||||
unp = sotounpcb(so); | |||||
if (unp == NULL) | if (unp == NULL) | ||||
goto done; | goto done; | ||||
UNP_PCB_LOCK(unp); | UNP_PCB_LOCK(unp); | ||||
if (unp->unp_vnode == vp) { | if (unp->unp_vnode == vp) { | ||||
VOP_UNP_DETACH(vp); | VOP_UNP_DETACH(vp); | ||||
unp->unp_vnode = NULL; | unp->unp_vnode = NULL; | ||||
active = 1; | active = 1; | ||||
} | } | ||||
Show All 17 Lines | |||||
static void | static void | ||||
db_print_unpflags(int unp_flags) | db_print_unpflags(int unp_flags) | ||||
{ | { | ||||
int comma; | int comma; | ||||
comma = 0; | comma = 0; | ||||
if (unp_flags & UNP_HAVEPC) { | if (unp_flags & UNP_HAVEPC) { | ||||
db_printf("%sUNP_HAVEPC", comma ? ", " : ""); | db_printf("%sUNP_HAVEPC", comma ? ", " : ""); | ||||
comma = 1; | |||||
} | |||||
if (unp_flags & UNP_HAVEPCCACHED) { | |||||
db_printf("%sUNP_HAVEPCCACHED", comma ? ", " : ""); | |||||
comma = 1; | comma = 1; | ||||
} | } | ||||
if (unp_flags & UNP_WANTCRED) { | if (unp_flags & UNP_WANTCRED) { | ||||
db_printf("%sUNP_WANTCRED", comma ? ", " : ""); | db_printf("%sUNP_WANTCRED", comma ? ", " : ""); | ||||
comma = 1; | comma = 1; | ||||
} | } | ||||
if (unp_flags & UNP_CONNWAIT) { | if (unp_flags & UNP_CONNWAIT) { | ||||
db_printf("%sUNP_CONNWAIT", comma ? ", " : ""); | db_printf("%sUNP_CONNWAIT", comma ? ", " : ""); | ||||
▲ Show 20 Lines • Show All 84 Lines • Show Last 20 Lines |