Update to FreeBSD head 2017-08-01

Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c.

Update #3472.
This commit is contained in:
Sebastian Huber
2018-08-07 14:56:50 +02:00
parent de261e0404
commit c37f9fba70
169 changed files with 6857 additions and 3262 deletions

View File

@@ -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;