mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-17 16:42:02 +08:00
Update to FreeBSD head 2017-08-01
Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c. Update #3472.
This commit is contained in:
@@ -202,10 +202,9 @@ SYSCTL_INT(_net_local, OID_AUTO, deferred, CTLFLAG_RD,
|
||||
/*
|
||||
* Locking and synchronization:
|
||||
*
|
||||
* Three types of locks exit in the local domain socket implementation: a
|
||||
* global list mutex, a global linkage rwlock, and per-unpcb mutexes. Of the
|
||||
* global locks, the list lock protects the socket count, global generation
|
||||
* number, and stream/datagram global lists. The linkage lock protects the
|
||||
* Two types of locks exist in the local domain socket implementation: a
|
||||
* a global linkage rwlock and per-unpcb mutexes. The linkage lock protects
|
||||
* the socket count, global generation number, stream/datagram global lists and
|
||||
* interconnection of unpcbs, the v_socket and unp_vnode pointers, and can be
|
||||
* held exclusively over the acquisition of multiple unpcb locks to prevent
|
||||
* deadlock.
|
||||
@@ -246,7 +245,6 @@ SYSCTL_INT(_net_local, OID_AUTO, deferred, CTLFLAG_RD,
|
||||
* to perform namei() and other file system operations.
|
||||
*/
|
||||
static struct rwlock unp_link_rwlock;
|
||||
static struct mtx unp_list_lock;
|
||||
static struct mtx unp_defers_lock;
|
||||
|
||||
#define UNP_LINK_LOCK_INIT() rw_init(&unp_link_rwlock, \
|
||||
@@ -263,11 +261,7 @@ static struct mtx unp_defers_lock;
|
||||
#define UNP_LINK_WUNLOCK() rw_wunlock(&unp_link_rwlock)
|
||||
#define UNP_LINK_WLOCK_ASSERT() rw_assert(&unp_link_rwlock, \
|
||||
RA_WLOCKED)
|
||||
|
||||
#define UNP_LIST_LOCK_INIT() mtx_init(&unp_list_lock, \
|
||||
"unp_list_lock", NULL, MTX_DEF)
|
||||
#define UNP_LIST_LOCK() mtx_lock(&unp_list_lock)
|
||||
#define UNP_LIST_UNLOCK() mtx_unlock(&unp_list_lock)
|
||||
#define UNP_LINK_WOWNED() rw_wowned(&unp_link_rwlock)
|
||||
|
||||
#define UNP_DEFERRED_LOCK_INIT() mtx_init(&unp_defers_lock, \
|
||||
"unp_defer", NULL, MTX_DEF)
|
||||
@@ -417,6 +411,7 @@ uipc_attach(struct socket *so, int proto, struct thread *td)
|
||||
u_long sendspace, recvspace;
|
||||
struct unpcb *unp;
|
||||
int error;
|
||||
bool locked;
|
||||
|
||||
KASSERT(so->so_pcb == NULL, ("uipc_attach: so_pcb != NULL"));
|
||||
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
|
||||
@@ -451,10 +446,12 @@ uipc_attach(struct socket *so, int proto, struct thread *td)
|
||||
unp->unp_socket = so;
|
||||
so->so_pcb = unp;
|
||||
unp->unp_refcount = 1;
|
||||
if (so->so_head != NULL)
|
||||
if (so->so_listen != NULL)
|
||||
unp->unp_flags |= UNP_NASCENT;
|
||||
|
||||
UNP_LIST_LOCK();
|
||||
if ((locked = UNP_LINK_WOWNED()) == false)
|
||||
UNP_LINK_WLOCK();
|
||||
|
||||
unp->unp_gencnt = ++unp_gencnt;
|
||||
unp_count++;
|
||||
switch (so->so_type) {
|
||||
@@ -473,7 +470,9 @@ uipc_attach(struct socket *so, int proto, struct thread *td)
|
||||
default:
|
||||
panic("uipc_attach");
|
||||
}
|
||||
UNP_LIST_UNLOCK();
|
||||
|
||||
if (locked == false)
|
||||
UNP_LINK_WUNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -516,6 +515,14 @@ static const IMFS_node_control rtems_uipc_imfs_control =
|
||||
static const IMFS_node_control rtems_uipc_imfs_zombi_control =
|
||||
IMFS_GENERIC_INITIALIZER(&rtems_filesystem_handlers_default, NULL,
|
||||
IMFS_node_destroy_default);
|
||||
|
||||
static void
|
||||
VOP_UNP_DETACH(IMFS_generic_t *vp)
|
||||
{
|
||||
|
||||
vp->Node.control = &rtems_uipc_imfs_zombi_control;
|
||||
vp->context = NULL;
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
static int
|
||||
uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
@@ -630,7 +637,7 @@ restart:
|
||||
UNP_LINK_WLOCK();
|
||||
UNP_PCB_LOCK(unp);
|
||||
#ifndef __rtems__
|
||||
VOP_UNP_BIND(vp, unp->unp_socket);
|
||||
VOP_UNP_BIND(vp, unp);
|
||||
unp->unp_vnode = vp;
|
||||
#endif /* __rtems__ */
|
||||
unp->unp_addr = soun;
|
||||
@@ -690,6 +697,11 @@ static void
|
||||
uipc_close(struct socket *so)
|
||||
{
|
||||
struct unpcb *unp, *unp2;
|
||||
#ifndef __rtems__
|
||||
struct vnode *vp;
|
||||
#else /* __rtems__ */
|
||||
IMFS_generic_t *vp;
|
||||
#endif /* __rtems__ */
|
||||
|
||||
unp = sotounpcb(so);
|
||||
KASSERT(unp != NULL, ("uipc_close: unp == NULL"));
|
||||
@@ -702,8 +714,16 @@ uipc_close(struct socket *so)
|
||||
unp_disconnect(unp, 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_LINK_WUNLOCK();
|
||||
#ifndef __rtems__
|
||||
if (vp)
|
||||
vrele(vp);
|
||||
#endif /* __rtems__ */
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -747,29 +767,16 @@ uipc_detach(struct socket *so)
|
||||
local_unp_rights = 0;
|
||||
#endif /* __rtems__ */
|
||||
|
||||
UNP_LIST_LOCK();
|
||||
UNP_LINK_WLOCK();
|
||||
LIST_REMOVE(unp, unp_link);
|
||||
unp->unp_gencnt = ++unp_gencnt;
|
||||
--unp_count;
|
||||
UNP_LIST_UNLOCK();
|
||||
|
||||
if ((unp->unp_flags & UNP_NASCENT) != 0) {
|
||||
UNP_PCB_LOCK(unp);
|
||||
goto teardown;
|
||||
}
|
||||
UNP_LINK_WLOCK();
|
||||
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) {
|
||||
#ifndef __rtems__
|
||||
VOP_UNP_DETACH(vp);
|
||||
#else /* __rtems__ */
|
||||
vp->Node.control = &rtems_uipc_imfs_zombi_control;
|
||||
vp->context = NULL;
|
||||
#endif /* __rtems__ */
|
||||
unp->unp_vnode = NULL;
|
||||
}
|
||||
unp2 = unp->unp_conn;
|
||||
@@ -793,8 +800,8 @@ uipc_detach(struct socket *so)
|
||||
#ifndef __rtems__
|
||||
local_unp_rights = unp_rights;
|
||||
#endif /* __rtems__ */
|
||||
UNP_LINK_WUNLOCK();
|
||||
teardown:
|
||||
UNP_LINK_WUNLOCK();
|
||||
unp->unp_socket->so_pcb = NULL;
|
||||
saved_unp_addr = unp->unp_addr;
|
||||
unp->unp_addr = NULL;
|
||||
@@ -860,7 +867,6 @@ uipc_listen(struct socket *so, int backlog, struct thread *td)
|
||||
error = solisten_proto_check(so);
|
||||
if (error == 0) {
|
||||
cru2x(td->td_ucred, &unp->unp_peercred);
|
||||
unp->unp_flags |= UNP_HAVEPCCACHED;
|
||||
solisten_proto(so, backlog);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
@@ -1439,7 +1445,7 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
|
||||
#else /* __rtems__ */
|
||||
struct IMFS_jnode_tt *vp;
|
||||
#endif /* __rtems__ */
|
||||
struct socket *so2, *so3;
|
||||
struct socket *so2;
|
||||
struct unpcb *unp, *unp2, *unp3;
|
||||
#ifndef __rtems__
|
||||
struct nameidata nd;
|
||||
@@ -1450,7 +1456,9 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
|
||||
const rtems_filesystem_location_info_t *currentloc;
|
||||
#endif /* __rtems__ */
|
||||
struct sockaddr *sa;
|
||||
#ifndef __rtems__
|
||||
cap_rights_t rights;
|
||||
#endif /* __rtems__ */
|
||||
int error, len;
|
||||
|
||||
if (nam->sa_family != AF_UNIX)
|
||||
@@ -1535,34 +1543,38 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
|
||||
*/
|
||||
UNP_LINK_WLOCK();
|
||||
#ifndef __rtems__
|
||||
VOP_UNP_CONNECT(vp, &so2);
|
||||
VOP_UNP_CONNECT(vp, &unp2);
|
||||
if (unp2 == NULL) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad2;
|
||||
}
|
||||
so2 = unp2->unp_socket;
|
||||
#else /* __rtems__ */
|
||||
so2 = IMFS_generic_get_context_by_node(vp);
|
||||
#endif /* __rtems__ */
|
||||
if (so2 == NULL) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad2;
|
||||
}
|
||||
unp2 = sotounpcb(so2);
|
||||
#endif /* __rtems__ */
|
||||
if (so->so_type != so2->so_type) {
|
||||
error = EPROTOTYPE;
|
||||
goto bad2;
|
||||
}
|
||||
UNP_PCB_LOCK(unp);
|
||||
UNP_PCB_LOCK(unp2);
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
||||
if (so2->so_options & SO_ACCEPTCONN) {
|
||||
CURVNET_SET(so2->so_vnet);
|
||||
so3 = sonewconn(so2, 0);
|
||||
so2 = sonewconn(so2, 0);
|
||||
CURVNET_RESTORE();
|
||||
} else
|
||||
so3 = NULL;
|
||||
if (so3 == NULL) {
|
||||
so2 = NULL;
|
||||
if (so2 == NULL) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad2;
|
||||
goto bad3;
|
||||
}
|
||||
unp = sotounpcb(so);
|
||||
unp2 = sotounpcb(so2);
|
||||
unp3 = sotounpcb(so3);
|
||||
UNP_PCB_LOCK(unp);
|
||||
UNP_PCB_LOCK(unp2);
|
||||
unp3 = sotounpcb(so2);
|
||||
UNP_PCB_LOCK(unp3);
|
||||
if (unp2->unp_addr != NULL) {
|
||||
bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len);
|
||||
@@ -1583,30 +1595,24 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
|
||||
* listen(); uipc_listen() cached that process's credentials
|
||||
* 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,
|
||||
sizeof(unp->unp_peercred));
|
||||
unp->unp_flags |= UNP_HAVEPC;
|
||||
if (unp2->unp_flags & UNP_WANTCRED)
|
||||
unp3->unp_flags |= UNP_WANTCRED;
|
||||
UNP_PCB_UNLOCK(unp3);
|
||||
UNP_PCB_UNLOCK(unp2);
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
unp2 = unp3;
|
||||
#ifdef MAC
|
||||
mac_socketpeer_set_from_socket(so, so3);
|
||||
mac_socketpeer_set_from_socket(so3, so);
|
||||
mac_socketpeer_set_from_socket(so, so2);
|
||||
mac_socketpeer_set_from_socket(so2, so);
|
||||
#endif
|
||||
|
||||
so2 = so3;
|
||||
}
|
||||
unp = sotounpcb(so);
|
||||
KASSERT(unp != NULL, ("unp_connect: unp == NULL"));
|
||||
unp2 = sotounpcb(so2);
|
||||
KASSERT(unp2 != NULL, ("unp_connect: unp2 == NULL"));
|
||||
UNP_PCB_LOCK(unp);
|
||||
UNP_PCB_LOCK(unp2);
|
||||
|
||||
KASSERT(unp2 != NULL && so2 != NULL && unp2->unp_socket == so2 &&
|
||||
sotounpcb(so2) == unp2,
|
||||
("%s: unp2 %p so2 %p", __func__, unp2, so2));
|
||||
error = unp_connect2(so, so2, PRU_CONNECT);
|
||||
bad3:
|
||||
UNP_PCB_UNLOCK(unp2);
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
bad2:
|
||||
@@ -1750,10 +1756,10 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
* OK, now we're committed to doing something.
|
||||
*/
|
||||
xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK);
|
||||
UNP_LIST_LOCK();
|
||||
UNP_LINK_RLOCK();
|
||||
gencnt = unp_gencnt;
|
||||
n = unp_count;
|
||||
UNP_LIST_UNLOCK();
|
||||
UNP_LINK_RUNLOCK();
|
||||
|
||||
xug->xug_len = sizeof *xug;
|
||||
xug->xug_count = n;
|
||||
@@ -1767,7 +1773,7 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK);
|
||||
|
||||
UNP_LIST_LOCK();
|
||||
UNP_LINK_RLOCK();
|
||||
for (unp = LIST_FIRST(head), i = 0; unp && i < n;
|
||||
unp = LIST_NEXT(unp, unp_link)) {
|
||||
UNP_PCB_LOCK(unp);
|
||||
@@ -1782,7 +1788,7 @@ unp_pcblist(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
UNP_PCB_UNLOCK(unp);
|
||||
}
|
||||
UNP_LIST_UNLOCK();
|
||||
UNP_LINK_RUNLOCK();
|
||||
n = i; /* In case we lost some during malloc. */
|
||||
|
||||
error = 0;
|
||||
@@ -2044,7 +2050,6 @@ unp_init(void)
|
||||
TASK_INIT(&unp_defer_task, 0, unp_process_defers, NULL);
|
||||
#endif /* __rtems__ */
|
||||
UNP_LINK_LOCK_INIT();
|
||||
UNP_LIST_LOCK_INIT();
|
||||
UNP_DEFERRED_LOCK_INIT();
|
||||
}
|
||||
|
||||
@@ -2396,8 +2401,7 @@ unp_accessable(struct filedescent **fdep, int fdcount)
|
||||
static void
|
||||
unp_gc_process(struct unpcb *unp)
|
||||
{
|
||||
struct socket *soa;
|
||||
struct socket *so;
|
||||
struct socket *so, *soa;
|
||||
struct file *fp;
|
||||
|
||||
/* Already processed. */
|
||||
@@ -2417,28 +2421,30 @@ unp_gc_process(struct unpcb *unp)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all sockets we reference with RIGHTS.
|
||||
*/
|
||||
so = unp->unp_socket;
|
||||
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_LOCK(so);
|
||||
if (SOLISTENING(so)) {
|
||||
/*
|
||||
* Mark all sockets in our accept queue.
|
||||
*/
|
||||
TAILQ_FOREACH(soa, &so->sol_comp, so_list) {
|
||||
if (sotounpcb(soa)->unp_gcflag & UNPGC_IGNORE_RIGHTS)
|
||||
continue;
|
||||
SOCKBUF_LOCK(&soa->so_rcv);
|
||||
unp_scan(soa->so_rcv.sb_mb, unp_accessable);
|
||||
SOCKBUF_UNLOCK(&soa->so_rcv);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all sockets in our accept queue.
|
||||
*/
|
||||
ACCEPT_LOCK();
|
||||
TAILQ_FOREACH(soa, &so->so_comp, so_list) {
|
||||
if ((sotounpcb(soa)->unp_gcflag & UNPGC_IGNORE_RIGHTS) != 0)
|
||||
continue;
|
||||
SOCKBUF_LOCK(&soa->so_rcv);
|
||||
unp_scan(soa->so_rcv.sb_mb, unp_accessable);
|
||||
SOCKBUF_UNLOCK(&soa->so_rcv);
|
||||
}
|
||||
ACCEPT_UNLOCK();
|
||||
SOCK_UNLOCK(so);
|
||||
unp->unp_gcflag |= UNPGC_SCANNED;
|
||||
}
|
||||
|
||||
@@ -2461,7 +2467,7 @@ unp_gc(__unused void *arg, int pending)
|
||||
int i, total;
|
||||
|
||||
unp_taskcount++;
|
||||
UNP_LIST_LOCK();
|
||||
UNP_LINK_RLOCK();
|
||||
/*
|
||||
* First clear all gc flags from previous runs, apart from
|
||||
* UNPGC_IGNORE_RIGHTS.
|
||||
@@ -2484,7 +2490,7 @@ unp_gc(__unused void *arg, int pending)
|
||||
LIST_FOREACH(unp, *head, unp_link)
|
||||
unp_gc_process(unp);
|
||||
} while (unp_marked);
|
||||
UNP_LIST_UNLOCK();
|
||||
UNP_LINK_RUNLOCK();
|
||||
if (unp_unreachable == 0)
|
||||
return;
|
||||
|
||||
@@ -2499,7 +2505,6 @@ unp_gc(__unused void *arg, int pending)
|
||||
* as as unreachable and store them locally.
|
||||
*/
|
||||
UNP_LINK_RLOCK();
|
||||
UNP_LIST_LOCK();
|
||||
for (total = 0, head = heads; *head != NULL; head++)
|
||||
LIST_FOREACH(unp, *head, unp_link)
|
||||
if ((unp->unp_gcflag & UNPGC_DEAD) != 0) {
|
||||
@@ -2512,7 +2517,6 @@ unp_gc(__unused void *arg, int pending)
|
||||
KASSERT(total <= unp_unreachable,
|
||||
("unp_gc: incorrect unreachable count."));
|
||||
}
|
||||
UNP_LIST_UNLOCK();
|
||||
UNP_LINK_RUNLOCK();
|
||||
|
||||
/*
|
||||
@@ -2555,10 +2559,11 @@ unp_dispose(struct socket *so)
|
||||
struct unpcb *unp;
|
||||
|
||||
unp = sotounpcb(so);
|
||||
UNP_LIST_LOCK();
|
||||
UNP_LINK_WLOCK();
|
||||
unp->unp_gcflag |= UNPGC_IGNORE_RIGHTS;
|
||||
UNP_LIST_UNLOCK();
|
||||
unp_dispose_mbuf(so->so_rcv.sb_mb);
|
||||
UNP_LINK_WUNLOCK();
|
||||
if (!SOLISTENING(so))
|
||||
unp_dispose_mbuf(so->so_rcv.sb_mb);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2613,7 +2618,6 @@ unp_scan(struct mbuf *m0, void (*op)(struct filedescent **, int))
|
||||
void
|
||||
vfs_unp_reclaim(struct vnode *vp)
|
||||
{
|
||||
struct socket *so;
|
||||
struct unpcb *unp;
|
||||
int active;
|
||||
|
||||
@@ -2623,10 +2627,7 @@ vfs_unp_reclaim(struct vnode *vp)
|
||||
|
||||
active = 0;
|
||||
UNP_LINK_WLOCK();
|
||||
VOP_UNP_CONNECT(vp, &so);
|
||||
if (so == NULL)
|
||||
goto done;
|
||||
unp = sotounpcb(so);
|
||||
VOP_UNP_CONNECT(vp, &unp);
|
||||
if (unp == NULL)
|
||||
goto done;
|
||||
UNP_PCB_LOCK(unp);
|
||||
@@ -2663,10 +2664,6 @@ db_print_unpflags(int unp_flags)
|
||||
db_printf("%sUNP_HAVEPC", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (unp_flags & UNP_HAVEPCCACHED) {
|
||||
db_printf("%sUNP_HAVEPCCACHED", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (unp_flags & UNP_WANTCRED) {
|
||||
db_printf("%sUNP_WANTCRED", comma ? ", " : "");
|
||||
comma = 1;
|
||||
|
Reference in New Issue
Block a user