sync with OpenBSD -current

This commit is contained in:
purplerain 2024-05-21 00:16:53 +00:00
parent 57ecf9bd1d
commit b5356a44af
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
156 changed files with 3600 additions and 2644 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_socket.c,v 1.333 2024/05/03 17:43:09 mvs Exp $ */
/* $OpenBSD: uipc_socket.c,v 1.335 2024/05/17 19:11:14 mvs Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@ -66,7 +66,6 @@ void soreaper(void *);
void soput(void *);
int somove(struct socket *, int);
void sorflush(struct socket *);
void sorflush_locked(struct socket *);
void filt_sordetach(struct knote *kn);
int filt_soread(struct knote *kn, long hint);
@ -166,6 +165,7 @@ soalloc(const struct protosw *prp, int wait)
break;
}
break;
case AF_KEY:
case AF_UNIX:
so->so_snd.sb_flags |= SB_MTXLOCK;
so->so_rcv.sb_flags |= SB_MTXLOCK;
@ -606,11 +606,11 @@ sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top,
#define snderr(errno) { error = errno; goto release; }
restart:
if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
goto out;
if (dosolock)
solock_shared(so);
restart:
if ((error = sblock(so, &so->so_snd, SBLOCKWAIT(flags))) != 0)
goto out;
sb_mtx_lock(&so->so_snd);
so->so_snd.sb_state |= SS_ISSENDING;
do {
@ -643,15 +643,12 @@ restart:
(atomic || space < so->so_snd.sb_lowat))) {
if (flags & MSG_DONTWAIT)
snderr(EWOULDBLOCK);
sbunlock(so, &so->so_snd);
if (so->so_snd.sb_flags & SB_MTXLOCK)
error = sbwait_locked(so, &so->so_snd);
else
error = sbwait(so, &so->so_snd);
sbunlock(&so->so_snd);
error = sbwait(so, &so->so_snd);
so->so_snd.sb_state &= ~SS_ISSENDING;
sb_mtx_unlock(&so->so_snd);
if (dosolock)
sounlock_shared(so);
if (error)
goto out;
goto restart;
@ -705,10 +702,10 @@ restart:
release:
so->so_snd.sb_state &= ~SS_ISSENDING;
sb_mtx_unlock(&so->so_snd);
sbunlock(so, &so->so_snd);
out:
if (dosolock)
sounlock_shared(so);
sbunlock(&so->so_snd);
out:
m_freem(top);
m_freem(control);
return (error);
@ -875,11 +872,11 @@ bad:
if (mp)
*mp = NULL;
restart:
if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)
return (error);
if (dosolock)
solock_shared(so);
restart:
if ((error = sblock(so, &so->so_rcv, SBLOCKWAIT(flags))) != 0)
goto out;
sb_mtx_lock(&so->so_rcv);
m = so->so_rcv.sb_mb;
@ -944,25 +941,13 @@ restart:
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
if (so->so_rcv.sb_flags & SB_MTXLOCK) {
sbunlock_locked(so, &so->so_rcv);
if (dosolock)
sounlock_shared(so);
error = sbwait_locked(so, &so->so_rcv);
sb_mtx_unlock(&so->so_rcv);
if (error)
return (error);
if (dosolock)
solock_shared(so);
} else {
sb_mtx_unlock(&so->so_rcv);
sbunlock(so, &so->so_rcv);
error = sbwait(so, &so->so_rcv);
if (error) {
sounlock_shared(so);
return (error);
}
}
sbunlock(&so->so_rcv);
error = sbwait(so, &so->so_rcv);
sb_mtx_unlock(&so->so_rcv);
if (dosolock)
sounlock_shared(so);
if (error)
return (error);
goto restart;
}
dontblock:
@ -1202,21 +1187,12 @@ dontblock:
break;
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
if (dosolock) {
if (sbwait(so, &so->so_rcv)) {
sb_mtx_unlock(&so->so_rcv);
error = sbwait(so, &so->so_rcv);
if (error) {
sbunlock(so, &so->so_rcv);
if (dosolock)
sounlock_shared(so);
return (0);
}
sb_mtx_lock(&so->so_rcv);
} else {
if (sbwait_locked(so, &so->so_rcv)) {
sb_mtx_unlock(&so->so_rcv);
sbunlock(so, &so->so_rcv);
return (0);
}
sbunlock(&so->so_rcv);
return (0);
}
if ((m = so->so_rcv.sb_mb) != NULL)
nextrecord = m->m_nextpkt;
@ -1258,7 +1234,7 @@ dontblock:
(flags & MSG_EOR) == 0 &&
(so->so_rcv.sb_state & SS_CANTRCVMORE) == 0) {
sb_mtx_unlock(&so->so_rcv);
sbunlock(so, &so->so_rcv);
sbunlock(&so->so_rcv);
goto restart;
}
@ -1269,10 +1245,9 @@ dontblock:
*flagsp |= flags;
release:
sb_mtx_unlock(&so->so_rcv);
sbunlock(so, &so->so_rcv);
out:
if (dosolock)
sounlock_shared(so);
sbunlock(&so->so_rcv);
return (error);
}
@ -1302,48 +1277,33 @@ soshutdown(struct socket *so, int how)
}
void
sorflush_locked(struct socket *so)
sorflush(struct socket *so)
{
struct sockbuf *sb = &so->so_rcv;
struct mbuf *m;
const struct protosw *pr = so->so_proto;
int error;
if ((sb->sb_flags & SB_MTXLOCK) == 0)
soassertlocked(so);
error = sblock(so, sb, SBL_WAIT | SBL_NOINTR);
error = sblock(sb, SBL_WAIT | SBL_NOINTR);
/* with SBL_WAIT and SLB_NOINTR sblock() must not fail */
KASSERT(error == 0);
if (sb->sb_flags & SB_MTXLOCK)
solock(so);
solock_shared(so);
socantrcvmore(so);
if (sb->sb_flags & SB_MTXLOCK)
sounlock(so);
mtx_enter(&sb->sb_mtx);
m = sb->sb_mb;
memset(&sb->sb_startzero, 0,
(caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero);
sb->sb_timeo_nsecs = INFSLP;
mtx_leave(&sb->sb_mtx);
sbunlock(so, sb);
sounlock_shared(so);
sbunlock(sb);
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
(*pr->pr_domain->dom_dispose)(m);
m_purge(m);
}
void
sorflush(struct socket *so)
{
if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0)
solock_shared(so);
sorflush_locked(so);
if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0)
sounlock_shared(so);
}
#ifdef SOCKET_SPLICE
#define so_splicelen so_sp->ssp_len
@ -1355,7 +1315,7 @@ sorflush(struct socket *so)
int
sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
{
struct file *fp = NULL;
struct file *fp;
struct socket *sosp;
struct taskq *tq;
int error = 0;
@ -1367,6 +1327,29 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
if (tv && (tv->tv_sec < 0 || !timerisvalid(tv)))
return (EINVAL);
/* If no fd is given, unsplice by removing existing link. */
if (fd < 0) {
if ((error = sblock(&so->so_rcv, SBL_WAIT)) != 0)
return (error);
solock(so);
if (so->so_options & SO_ACCEPTCONN) {
error = EOPNOTSUPP;
goto out;
}
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
error = ENOTCONN;
goto out;
}
if (so->so_sp && so->so_sp->ssp_socket)
sounsplice(so, so->so_sp->ssp_socket, 0);
out:
sounlock(so);
sbunlock(&so->so_rcv);
return (error);
}
if (sosplice_taskq == NULL) {
rw_enter_write(&sosplice_lock);
if (sosplice_taskq == NULL) {
@ -1386,65 +1369,47 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
membar_consumer();
}
if (so->so_rcv.sb_flags & SB_MTXLOCK) {
if ((error = sblock(so, &so->so_rcv, SBL_WAIT)) != 0)
return (error);
solock(so);
} else {
solock(so);
if ((error = sblock(so, &so->so_rcv, SBL_WAIT)) != 0) {
sounlock(so);
return (error);
}
/* Find sosp, the drain socket where data will be spliced into. */
if ((error = getsock(curproc, fd, &fp)) != 0)
return (error);
sosp = fp->f_data;
if (sosp->so_proto->pr_usrreqs->pru_send !=
so->so_proto->pr_usrreqs->pru_send) {
error = EPROTONOSUPPORT;
goto frele;
}
if (so->so_options & SO_ACCEPTCONN) {
if ((error = sblock(&so->so_rcv, SBL_WAIT)) != 0)
goto frele;
if ((error = sblock(&sosp->so_snd, SBL_WAIT)) != 0) {
sbunlock(&so->so_rcv);
goto frele;
}
solock(so);
if ((so->so_options & SO_ACCEPTCONN) ||
(sosp->so_options & SO_ACCEPTCONN)) {
error = EOPNOTSUPP;
goto out;
goto release;
}
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
error = ENOTCONN;
goto out;
}
if (so->so_sp == NULL)
so->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
/* If no fd is given, unsplice by removing existing link. */
if (fd < 0) {
if (so->so_sp->ssp_socket)
sounsplice(so, so->so_sp->ssp_socket, 0);
goto out;
}
/* Find sosp, the drain socket where data will be spliced into. */
if ((error = getsock(curproc, fd, &fp)) != 0)
goto out;
sosp = fp->f_data;
if (sosp->so_proto->pr_usrreqs->pru_send !=
so->so_proto->pr_usrreqs->pru_send) {
error = EPROTONOSUPPORT;
goto out;
}
if (sosp->so_sp == NULL)
sosp->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
if ((error = sblock(sosp, &sosp->so_snd, SBL_WAIT)) != 0) {
goto out;
}
if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
error = EBUSY;
goto release;
}
if (sosp->so_options & SO_ACCEPTCONN) {
error = EOPNOTSUPP;
goto release;
}
if ((sosp->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) {
error = ENOTCONN;
goto release;
}
if (so->so_sp == NULL)
so->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
if (sosp->so_sp == NULL)
sosp->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
error = EBUSY;
goto release;
}
/* Splice so and sosp together. */
mtx_enter(&so->so_rcv.sb_mtx);
@ -1472,18 +1437,11 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
}
release:
sbunlock(sosp, &sosp->so_snd);
out:
if (so->so_rcv.sb_flags & SB_MTXLOCK) {
sounlock(so);
sbunlock(so, &so->so_rcv);
} else {
sbunlock(so, &so->so_rcv);
sounlock(so);
}
if (fp)
FRELE(fp, curproc);
sounlock(so);
sbunlock(&sosp->so_snd);
sbunlock(&so->so_rcv);
frele:
FRELE(fp, curproc);
return (error);
}