Sockets and files have one flag each to indicate the I/O mode is
non-blocking. This is redundant. Keeping both flags in sync is
hard since races can happen between the two different layers.
So the diff below gets rid of SS_NBIO. It is fairly simple since
sosend(9) and soreceive(9) already take a MSG_DONTWAIT flag. So
I just moved the check before the calls.
I extended soclose(9) to also take a `flags' argument.
With this diff we get rid of a XXXSMP in the fifo code and we
prepare the terrain for getting `f_flag' out of the KERNEL_LOCK().
Comments? Oks?
Index: sys/kern/subr_log.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_log.c,v
retrieving revision 1.55
diff -u -p -r1.55 subr_log.c
--- sys/kern/subr_log.c 19 Feb 2018 08:59:52 -0000 1.55
+++ sys/kern/subr_log.c 12 Jul 2018 11:39:15 -0000
@@ -51,6 +51,7 @@
#include <sys/filedesc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <sys/fcntl.h>
#ifdef KTRACE
#include <sys/ktrace.h>
@@ -480,7 +481,8 @@ dosendsyslog(struct proc *p, const char
len = auio.uio_resid;
if (fp) {
- error = sosend(fp->f_data, NULL, &auio, NULL, NULL, 0);
+ int flags = (fp->f_flag & FNONBLOCK) ? MSG_DONTWAIT : 0;
+ error = sosend(fp->f_data, NULL, &auio, NULL, NULL, flags);
if (error == 0)
len -= auio.uio_resid;
} else if (constty || cn_devvp) {
Index: sys/kern/sys_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_socket.c,v
retrieving revision 1.39
diff -u -p -r1.39 sys_socket.c
--- sys/kern/sys_socket.c 10 Jul 2018 08:58:50 -0000 1.39
+++ sys/kern/sys_socket.c 12 Jul 2018 12:20:49 -0000
@@ -43,6 +43,7 @@
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/stat.h>
+#include <sys/fcntl.h>
#include <net/if.h>
#include <net/route.h>
@@ -60,18 +61,25 @@ struct fileops socketops = {
int
soo_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
{
+ struct socket *so = (struct socket *)fp->f_data;
+ int flags = 0;
+
+ if (fp->f_flag & FNONBLOCK)
+ flags |= MSG_DONTWAIT;
- return (soreceive((struct socket *)fp->f_data, (struct mbuf **)NULL,
- uio, (struct mbuf **)NULL, (struct mbuf **)NULL, (int *)NULL,
- (socklen_t)0));
+ return (soreceive(so, NULL, uio, NULL, NULL, &flags, 0));
}
int
soo_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
{
+ struct socket *so = (struct socket *)fp->f_data;
+ int flags = 0;
+
+ if (fp->f_flag & FNONBLOCK)
+ flags |= MSG_DONTWAIT;
- return (sosend((struct socket *)fp->f_data, (struct mbuf *)NULL,
- uio, (struct mbuf *)NULL, (struct mbuf *)NULL, 0));
+ return (sosend(so, NULL, uio, NULL, NULL, flags));
}
int
@@ -83,12 +91,6 @@ soo_ioctl(struct file *fp, u_long cmd, c
switch (cmd) {
case FIONBIO:
- s = solock(so);
- if (*(int *)data)
- so->so_state |= SS_NBIO;
- else
- so->so_state &= ~SS_NBIO;
- sounlock(so, s);
break;
case FIOASYNC:
@@ -210,10 +212,12 @@ soo_stat(struct file *fp, struct stat *u
int
soo_close(struct file *fp, struct proc *p)
{
- int error = 0;
+ int flags, error = 0;
- if (fp->f_data)
- error = soclose(fp->f_data);
+ if (fp->f_data) {
+ flags = (fp->f_flag & FNONBLOCK) ? MSG_DONTWAIT : 0;
+ error = soclose(fp->f_data, flags);
+ }
fp->f_data = 0;
return (error);
}
Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.225
diff -u -p -r1.225 uipc_socket.c
--- sys/kern/uipc_socket.c 5 Jul 2018 14:45:07 -0000 1.225
+++ sys/kern/uipc_socket.c 12 Jul 2018 12:21:49 -0000
@@ -244,7 +244,7 @@ sofree(struct socket *so, int s)
* Free socket when disconnect complete.
*/
int
-soclose(struct socket *so)
+soclose(struct socket *so, int flags)
{
struct socket *so2;
int s, error = 0;
@@ -270,7 +270,7 @@ soclose(struct socket *so)
}
if (so->so_options & SO_LINGER) {
if ((so->so_state & SS_ISDISCONNECTING) &&
- (so->so_state & SS_NBIO))
+ (flags & MSG_DONTWAIT))
goto drop;
while (so->so_state & SS_ISCONNECTED) {
error = sosleep(so, &so->so_timeo,
@@ -469,7 +469,7 @@ restart:
if (space < clen ||
(space - clen < resid &&
(atomic || space < so->so_snd.sb_lowat))) {
- if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT))
+ if (flags & MSG_DONTWAIT)
snderr(EWOULDBLOCK);
sbunlock(so, &so->so_snd);
error = sbwait(so, &so->so_snd);
@@ -664,8 +664,6 @@ soreceive(struct socket *so, struct mbuf
flags = *flagsp &~ MSG_EOR;
else
flags = 0;
- if (so->so_state & SS_NBIO)
- flags |= MSG_DONTWAIT;
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
s = solock(so);
@@ -748,7 +746,7 @@ restart:
}
if (uio->uio_resid == 0 && controlp == NULL)
goto release;
- if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
+ if (flags & MSG_DONTWAIT) {
error = EWOULDBLOCK;
goto release;
}
@@ -1128,8 +1126,7 @@ sosplice(struct socket *so, int fd, off_
/* If no fd is given, unsplice by removing existing link. */
if (fd < 0) {
/* Lock receive buffer. */
- if ((error = sblock(so, &so->so_rcv,
- (so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK)) != 0) {
+ if ((error = sblock(so, &so->so_rcv, M_WAITOK)) != 0) {
return (error);
}
if (so->so_sp->ssp_socket)
@@ -1157,8 +1154,7 @@ sosplice(struct socket *so, int fd, off_
}
/* Lock both receive and send buffer. */
- if ((error = sblock(so, &so->so_rcv,
- (so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK)) != 0) {
+ if ((error = sblock(so, &so->so_rcv, M_WAITOK)) != 0) {
goto frele;
}
if ((error = sblock(so, &sosp->so_snd, M_WAITOK)) != 0) {
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.177
diff -u -p -r1.177 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c 20 Jun 2018 10:52:49 -0000 1.177
+++ sys/kern/uipc_syscalls.c 12 Jul 2018 12:18:33 -0000
@@ -109,13 +109,11 @@ sys_socket(struct proc *p, void *v, regi
error = falloc(p, &fp, &fd);
if (error) {
fdpunlock(fdp);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
} else {
fp->f_flag = fflag;
fp->f_type = DTYPE_SOCKET;
fp->f_ops = &socketops;
- if (nonblock)
- so->so_state |= SS_NBIO;
so->so_state |= ss;
fp->f_data = so;
fdinsert(fdp, fd, cloexec, fp);
@@ -302,7 +300,7 @@ doaccept(struct proc *p, int sock, struc
error = EINVAL;
goto out;
}
- if ((head->so_state & SS_NBIO) && head->so_qlen == 0) {
+ if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
if (head->so_state & SS_CANTRCVMORE)
error = ECONNABORTED;
else
@@ -347,10 +345,6 @@ doaccept(struct proc *p, int sock, struc
error = copyaddrout(p, nam, name, namelen, anamelen);
out:
if (!error) {
- if (nflag & FNONBLOCK)
- so->so_state |= SS_NBIO;
- else
- so->so_state &= ~SS_NBIO;
sounlock(head, s);
fdplock(fdp);
fp->f_data = so;
@@ -416,7 +410,7 @@ sys_connect(struct proc *p, void *v, reg
error = soconnect(so, nam);
if (error)
goto bad;
- if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+ if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
error = EINPROGRESS;
goto out;
}
@@ -503,12 +497,6 @@ sys_socketpair(struct proc *p, void *v,
if (KTRPOINT(p, KTR_STRUCT))
ktrfds(p, sv, 2);
#endif
- if (nonblock) {
- (*fp1->f_ops->fo_ioctl)(fp1, FIONBIO, (caddr_t)&type,
- p);
- (*fp2->f_ops->fo_ioctl)(fp2, FIONBIO, (caddr_t)&type,
- p);
- }
fdinsert(fdp, sv[0], cloexec, fp1);
fdinsert(fdp, sv[1], cloexec, fp2);
fdpunlock(fdp);
@@ -529,10 +517,10 @@ free3:
KERNEL_UNLOCK();
free2:
if (so2 != NULL)
- (void)soclose(so2);
+ (void)soclose(so2, 0);
free1:
if (so1 != NULL)
- (void)soclose(so1);
+ (void)soclose(so1, 0);
return (error);
}
@@ -626,6 +614,8 @@ sendit(struct proc *p, int s, struct msg
if ((error = getsock(p, s, &fp)) != 0)
return (error);
so = fp->f_data;
+ if (fp->f_flag & FNONBLOCK)
+ flags |= MSG_DONTWAIT;
error = pledge_sendit(p, mp->msg_name);
if (error)
@@ -849,6 +839,8 @@ recvit(struct proc *p, int s, struct msg
}
#endif
len = auio.uio_resid;
+ if (fp->f_flag & FNONBLOCK)
+ mp->msg_flags |= MSG_DONTWAIT;
error = soreceive(fp->f_data, &from, &auio, NULL,
mp->msg_control ? &control : NULL,
&mp->msg_flags,
Index: sys/net/bfd.c
===================================================================
RCS file: /cvs/src/sys/net/bfd.c,v
retrieving revision 1.71
diff -u -p -r1.71 bfd.c
--- sys/net/bfd.c 6 Jun 2018 06:55:22 -0000 1.71
+++ sys/net/bfd.c 12 Jul 2018 12:19:31 -0000
@@ -250,14 +250,14 @@ bfd_clear_task(void *arg)
if (bfd->bc_so) {
/* remove upcall before calling soclose or it will be called */
bfd->bc_so->so_upcall = NULL;
- soclose(bfd->bc_so);
+ soclose(bfd->bc_so, MSG_DONTWAIT);
}
if (bfd->bc_soecho) {
bfd->bc_soecho->so_upcall = NULL;
- soclose(bfd->bc_soecho);
+ soclose(bfd->bc_soecho, MSG_DONTWAIT);
}
if (bfd->bc_sosend)
- soclose(bfd->bc_sosend);
+ soclose(bfd->bc_sosend, MSG_DONTWAIT);
rtfree(bfd->bc_rt);
bfd->bc_rt = NULL;
@@ -495,7 +495,7 @@ bfd_listener(struct bfd_config *bfd, uns
close:
m_free(m);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
return (NULL);
}
@@ -624,7 +624,7 @@ bfd_sender(struct bfd_config *bfd, unsig
close:
m_free(m);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
return (NULL);
}
Index: sys/net/if_pflow.c
===================================================================
RCS file: /cvs/src/sys/net/if_pflow.c,v
retrieving revision 1.88
diff -u -p -r1.88 if_pflow.c
--- sys/net/if_pflow.c 6 Jun 2018 06:55:22 -0000 1.88
+++ sys/net/if_pflow.c 12 Jul 2018 12:19:44 -0000
@@ -286,7 +286,7 @@ pflow_clone_destroy(struct ifnet *ifp)
mq_purge(&sc->sc_outputqueue);
m_freem(sc->send_nam);
if (sc->so != NULL) {
- error = soclose(sc->so);
+ error = soclose(sc->so, MSG_DONTWAIT);
sc->so = NULL;
}
if (sc->sc_flowdst != NULL)
@@ -349,7 +349,7 @@ pflow_set(struct pflow_softc *sc, struct
free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len);
sc->sc_flowdst = NULL;
if (sc->so != NULL) {
- soclose(sc->so);
+ soclose(sc->so, MSG_DONTWAIT);
sc->so = NULL;
}
}
@@ -395,7 +395,7 @@ pflow_set(struct pflow_softc *sc, struct
free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len);
sc->sc_flowsrc = NULL;
if (sc->so != NULL) {
- soclose(sc->so);
+ soclose(sc->so, MSG_DONTWAIT);
sc->so = NULL;
}
switch(pflowr->flowsrc.ss_family) {
@@ -445,14 +445,14 @@ pflow_set(struct pflow_softc *sc, struct
sounlock(so, s);
m_freem(m);
if (error) {
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
return (error);
}
}
sc->so = so;
}
} else if (!pflowvalidsockaddr(sc->sc_flowdst, 0)) {
- soclose(sc->so);
+ soclose(sc->so, MSG_DONTWAIT);
sc->so = NULL;
}
Index: sys/miscfs/fifofs/fifo_vnops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fifofs/fifo_vnops.c,v
retrieving revision 1.67
diff -u -p -r1.67 fifo_vnops.c
--- sys/miscfs/fifofs/fifo_vnops.c 6 Jun 2018 06:55:22 -0000 1.67
+++ sys/miscfs/fifofs/fifo_vnops.c 12 Jul 2018 12:23:43 -0000
@@ -136,15 +136,15 @@ fifo_open(void *v)
}
fip->fi_readsock = rso;
if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) {
- (void)soclose(rso);
+ (void)soclose(rso, MSG_DONTWAIT);
free(fip, M_VNODE, sizeof *fip);
vp->v_fifoinfo = NULL;
return (error);
}
fip->fi_writesock = wso;
if ((error = soconnect2(wso, rso)) != 0) {
- (void)soclose(wso);
- (void)soclose(rso);
+ (void)soclose(wso, MSG_DONTWAIT);
+ (void)soclose(rso, MSG_DONTWAIT);
free(fip, M_VNODE, sizeof *fip);
vp->v_fifoinfo = NULL;
return (error);
@@ -214,7 +214,7 @@ fifo_read(void *v)
struct vop_read_args *ap = v;
struct uio *uio = ap->a_uio;
struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
- int error;
+ int error, flags = 0;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_READ)
@@ -223,12 +223,11 @@ fifo_read(void *v)
if (uio->uio_resid == 0)
return (0);
if (ap->a_ioflag & IO_NDELAY)
- rso->so_state |= SS_NBIO;
+ flags = MSG_DONTWAIT;
VOP_UNLOCK(ap->a_vp);
- error = soreceive(rso, NULL, uio, NULL, NULL, NULL, 0);
+ error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0);
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
if (ap->a_ioflag & IO_NDELAY) {
- rso->so_state &= ~SS_NBIO;
if (error == EWOULDBLOCK &&
ap->a_vp->v_fifoinfo->fi_writers == 0)
error = 0;
@@ -245,20 +244,17 @@ fifo_write(void *v)
{
struct vop_write_args *ap = v;
struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
- int error;
+ int error, flags = 0;
#ifdef DIAGNOSTIC
if (ap->a_uio->uio_rw != UIO_WRITE)
panic("fifo_write mode");
#endif
- /* XXXSMP changing state w/o lock isn't safe. */
if (ap->a_ioflag & IO_NDELAY)
- wso->so_state |= SS_NBIO;
+ flags = MSG_DONTWAIT;
VOP_UNLOCK(ap->a_vp);
- error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
+ error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags);
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
- if (ap->a_ioflag & IO_NDELAY)
- wso->so_state &= ~SS_NBIO;
return (error);
}
@@ -384,8 +380,8 @@ fifo_close(void *v)
}
}
if (fip->fi_readers == 0 && fip->fi_writers == 0) {
- error1 = soclose(fip->fi_readsock);
- error2 = soclose(fip->fi_writesock);
+ error1 = soclose(fip->fi_readsock, MSG_DONTWAIT);
+ error2 = soclose(fip->fi_writesock, MSG_DONTWAIT);
free(fip, M_VNODE, sizeof *fip);
vp->v_fifoinfo = NULL;
}
@@ -402,8 +398,8 @@ fifo_reclaim(void *v)
if (fip == NULL)
return (0);
- soclose(fip->fi_readsock);
- soclose(fip->fi_writesock);
+ soclose(fip->fi_readsock, MSG_DONTWAIT);
+ soclose(fip->fi_writesock, MSG_DONTWAIT);
free(fip, M_VNODE, sizeof *fip);
vp->v_fifoinfo = NULL;
Index: sys/nfs/krpc_subr.c
===================================================================
RCS file: /cvs/src/sys/nfs/krpc_subr.c,v
retrieving revision 1.33
diff -u -p -r1.33 krpc_subr.c
--- sys/nfs/krpc_subr.c 6 Jun 2018 06:55:22 -0000 1.33
+++ sys/nfs/krpc_subr.c 12 Jul 2018 12:19:51 -0000
@@ -469,7 +469,7 @@ krpc_call(struct sockaddr_in *sa, u_int
m_freem(nam);
m_freem(mhead);
m_freem(from);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
return error;
}
Index: sys/nfs/nfs_boot.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_boot.c,v
retrieving revision 1.44
diff -u -p -r1.44 nfs_boot.c
--- sys/nfs/nfs_boot.c 14 Nov 2017 16:01:55 -0000 1.44
+++ sys/nfs/nfs_boot.c 12 Jul 2018 12:19:57 -0000
@@ -190,7 +190,7 @@ nfs_boot_init(struct nfs_diskless *nd, s
if (error)
panic("nfs_boot: set if addr, error=%d", error);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
if (ifa->ifa_addr->sa_family == AF_INET)
Index: sys/nfs/nfs_socket.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.129
diff -u -p -r1.129 nfs_socket.c
--- sys/nfs/nfs_socket.c 6 Jun 2018 06:55:22 -0000 1.129
+++ sys/nfs/nfs_socket.c 12 Jul 2018 12:20:04 -0000
@@ -433,7 +433,7 @@ nfs_disconnect(struct nfsmount *nmp)
so = nmp->nm_so;
nmp->nm_so = NULL;
soshutdown(so, SHUT_RDWR);
- soclose(so);
+ soclose(so, MSG_DONTWAIT);
}
}
Index: sys/sys/socketvar.h
===================================================================
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.85
diff -u -p -r1.85 socketvar.h
--- sys/sys/socketvar.h 10 Jul 2018 10:02:14 -0000 1.85
+++ sys/sys/socketvar.h 12 Jul 2018 12:20:10 -0000
@@ -148,7 +148,6 @@ struct socket {
#define SS_ISDISCONNECTED 0x800 /* socket disconnected from
peer */
#define SS_PRIV 0x080 /* privileged for broadcast,
raw... */
-#define SS_NBIO 0x100 /* non-blocking ops */
#define SS_ASYNC 0x200 /* async i/o notify */
#define SS_CONNECTOUT 0x1000 /* connect, not accept, at this
end */
#define SS_ISSENDING 0x2000 /* hint for lower layer */
@@ -312,7 +311,7 @@ int soaccept(struct socket *so, struct m
int sobind(struct socket *so, struct mbuf *nam, struct proc *p);
void socantrcvmore(struct socket *so);
void socantsendmore(struct socket *so);
-int soclose(struct socket *so);
+int soclose(struct socket *, int);
int soconnect(struct socket *so, struct mbuf *nam);
int soconnect2(struct socket *so1, struct socket *so2);
int socreate(int dom, struct socket **aso, int type, int proto);
Index: share/man/man9/socreate.9
===================================================================
RCS file: /cvs/src/share/man/man9/socreate.9,v
retrieving revision 1.9
diff -u -p -r1.9 socreate.9
--- share/man/man9/socreate.9 1 Sep 2017 15:52:03 -0000 1.9
+++ share/man/man9/socreate.9 12 Jul 2018 12:30:59 -0000
@@ -47,7 +47,7 @@
.Ft int
.Fn sobind "struct socket *so" "struct mbuf *nam" "struct proc *p"
.Ft void
-.Fn soclose "struct socket *so"
+.Fn soclose "struct socket *so" "int flags"
.Ft int
.Fn soconnect "struct socket *so" "struct mbuf *nam"
.Ft int
@@ -307,11 +307,6 @@ The caller may need to manually clear
if
.Fn soconnect
returns an error.
-.Pp
-The
-.Dv MSG_DONTWAIT
-flag is not implemented for
-.Fn sosend .
.Pp
This manual page does not describe how to register socket upcalls or monitor
a socket for readability/writability without using blocking I/O.