Introduce per-sockbuf `sb_state' to use it with SS_CANTSENDMORE.
authormvs <mvs@openbsd.org>
Sat, 21 Jan 2023 11:23:23 +0000 (11:23 +0000)
committermvs <mvs@openbsd.org>
Sat, 21 Jan 2023 11:23:23 +0000 (11:23 +0000)
This time, socket's buffer lock requires solock() to be held. As a part of
socket buffers standalone locking work, move socket state bits which
represent its buffers state to per buffer state.

Opposing the previous reverted diff, the SS_CANTSENDMORE definition left
as is, but it used only with `sb_state'. `sb_state' ored with original
`so_state' when socket's data exported to the userland, so the ABI kept as
it was.

Inputs from deraadt@.

ok bluhm@

sys/kern/kern_sysctl.c
sys/kern/sys_socket.c
sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/kern/uipc_usrreq.c
sys/miscfs/fifofs/fifo_vnops.c
sys/netinet/tcp_usrreq.c
sys/sys/socketvar.h

index 7bd6576..94ae40f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sysctl.c,v 1.409 2023/01/14 01:04:55 cheloha Exp $       */
+/*     $OpenBSD: kern_sysctl.c,v 1.410 2023/01/21 11:23:23 mvs Exp $   */
 /*     $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $     */
 
 /*-
@@ -1184,7 +1184,7 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp,
                }
 
                kf->so_type = so->so_type;
-               kf->so_state = so->so_state;
+               kf->so_state = so->so_state | so->so_snd.sb_state;
                if (show_pointers)
                        kf->so_pcb = PTRTOINT64(so->so_pcb);
                else
index 70c3b4d..ddf1bef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_socket.c,v 1.58 2022/12/12 08:30:22 tb Exp $      */
+/*     $OpenBSD: sys_socket.c,v 1.59 2023/01/21 11:23:23 mvs Exp $     */
 /*     $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $  */
 
 /*
@@ -151,7 +151,7 @@ soo_stat(struct file *fp, struct stat *ub, struct proc *p)
        solock(so);
        if ((so->so_state & SS_CANTRCVMORE) == 0 || so->so_rcv.sb_cc != 0)
                ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
-       if ((so->so_state & SS_CANTSENDMORE) == 0)
+       if ((so->so_snd.sb_state & SS_CANTSENDMORE) == 0)
                ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
        ub->st_uid = so->so_euid;
        ub->st_gid = so->so_egid;
index 821fddf..8b3d008 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket.c,v 1.293 2022/12/12 08:30:22 tb Exp $    */
+/*     $OpenBSD: uipc_socket.c,v 1.294 2023/01/21 11:23:23 mvs Exp $   */
 /*     $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $        */
 
 /*
@@ -580,7 +580,7 @@ restart:
                goto out;
        so->so_state |= SS_ISSENDING;
        do {
-               if (so->so_state & SS_CANTSENDMORE)
+               if (so->so_snd.sb_state & SS_CANTSENDMORE)
                        snderr(EPIPE);
                if (so->so_error) {
                        error = so->so_error;
@@ -1465,7 +1465,7 @@ somove(struct socket *so, int wait)
                error = so->so_error;
                goto release;
        }
-       if (sosp->so_state & SS_CANTSENDMORE) {
+       if (sosp->so_snd.sb_state & SS_CANTSENDMORE) {
                error = EPIPE;
                goto release;
        }
@@ -1659,7 +1659,8 @@ somove(struct socket *so, int wait)
                        if (o) {
                                error = pru_send(sosp, m, NULL, NULL);
                                if (error) {
-                                       if (sosp->so_state & SS_CANTSENDMORE)
+                                       if (sosp->so_snd.sb_state &
+                                           SS_CANTSENDMORE)
                                                error = EPIPE;
                                        m_freem(o);
                                        goto release;
@@ -1676,7 +1677,7 @@ somove(struct socket *so, int wait)
                        *mtod(o, caddr_t) = *mtod(m, caddr_t);
                        error = pru_sendoob(sosp, o, NULL, NULL);
                        if (error) {
-                               if (sosp->so_state & SS_CANTSENDMORE)
+                               if (sosp->so_snd.sb_state & SS_CANTSENDMORE)
                                        error = EPIPE;
                                m_freem(m);
                                goto release;
@@ -1697,7 +1698,7 @@ somove(struct socket *so, int wait)
                sosp->so_state &= ~SS_ISSENDING;
        error = pru_send(sosp, m, NULL, NULL);
        if (error) {
-               if (sosp->so_state & SS_CANTSENDMORE)
+               if (sosp->so_snd.sb_state & SS_CANTSENDMORE)
                        error = EPIPE;
                goto release;
        }
@@ -1714,7 +1715,8 @@ somove(struct socket *so, int wait)
        if (error)
                so->so_error = error;
        if (((so->so_state & SS_CANTRCVMORE) && so->so_rcv.sb_cc == 0) ||
-           (sosp->so_state & SS_CANTSENDMORE) || maxreached || error) {
+           (sosp->so_snd.sb_state & SS_CANTSENDMORE) ||
+           maxreached || error) {
                sounsplice(so, sosp, 0);
                return (0);
        }
@@ -1839,7 +1841,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
                        switch (optname) {
 
                        case SO_SNDBUF:
-                               if (so->so_state & SS_CANTSENDMORE)
+                               if (so->so_snd.sb_state & SS_CANTSENDMORE)
                                        return (EINVAL);
                                if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
                                    sbreserve(so, &so->so_snd, cnt))
@@ -2185,7 +2187,7 @@ filt_sowrite(struct knote *kn, long hint)
        soassertlocked(so);
 
        kn->kn_data = sbspace(so, &so->so_snd);
-       if (so->so_state & SS_CANTSENDMORE) {
+       if (so->so_snd.sb_state & SS_CANTSENDMORE) {
                kn->kn_flags |= EV_EOF;
                if (kn->kn_flags & __EV_POLL) {
                        if (so->so_state & SS_ISDISCONNECTED)
index 1d2bf57..3fb722b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket2.c,v 1.131 2022/12/12 08:30:22 tb Exp $   */
+/*     $OpenBSD: uipc_socket2.c,v 1.132 2023/01/21 11:23:23 mvs Exp $  */
 /*     $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $       */
 
 /*
@@ -142,7 +142,8 @@ soisdisconnecting(struct socket *so)
 {
        soassertlocked(so);
        so->so_state &= ~SS_ISCONNECTING;
-       so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
+       so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE);
+       so->so_snd.sb_state |= SS_CANTSENDMORE;
        wakeup(&so->so_timeo);
        sowwakeup(so);
        sorwakeup(so);
@@ -153,7 +154,8 @@ soisdisconnected(struct socket *so)
 {
        soassertlocked(so);
        so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
-       so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
+       so->so_state |= (SS_CANTRCVMORE|SS_ISDISCONNECTED);
+       so->so_snd.sb_state |= SS_CANTSENDMORE;
        wakeup(&so->so_timeo);
        sowwakeup(so);
        sorwakeup(so);
@@ -334,7 +336,7 @@ void
 socantsendmore(struct socket *so)
 {
        soassertlocked(so);
-       so->so_state |= SS_CANTSENDMORE;
+       so->so_snd.sb_state |= SS_CANTSENDMORE;
        sowwakeup(so);
 }
 
index e5922a9..b7d9d63 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_usrreq.c,v 1.197 2022/12/12 08:30:22 tb Exp $    */
+/*     $OpenBSD: uipc_usrreq.c,v 1.198 2023/01/21 11:23:23 mvs Exp $   */
 /*     $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $        */
 
 /*
@@ -509,7 +509,7 @@ uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
                        goto out;
        }
 
-       if (so->so_state & SS_CANTSENDMORE) {
+       if (so->so_snd.sb_state & SS_CANTSENDMORE) {
                error = EPIPE;
                goto dispose;
        }
index 33039a4..3c60b67 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fifo_vnops.c,v 1.98 2022/12/12 08:30:22 tb Exp $      */
+/*     $OpenBSD: fifo_vnops.c,v 1.99 2023/01/21 11:23:23 mvs Exp $     */
 /*     $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
 
 /*
@@ -174,7 +174,7 @@ fifo_open(void *v)
                }
                fip->fi_readers = fip->fi_writers = 0;
                solock(wso);
-               wso->so_state |= SS_CANTSENDMORE;
+               wso->so_snd.sb_state |= SS_CANTSENDMORE;
                wso->so_snd.sb_lowat = PIPE_BUF;
                sounlock(wso);
        } else {
@@ -185,7 +185,7 @@ fifo_open(void *v)
                fip->fi_readers++;
                if (fip->fi_readers == 1) {
                        solock(wso);
-                       wso->so_state &= ~SS_CANTSENDMORE;
+                       wso->so_snd.sb_state &= ~SS_CANTSENDMORE;
                        sounlock(wso);
                        if (fip->fi_writers > 0)
                                wakeup(&fip->fi_writers);
@@ -559,7 +559,7 @@ filt_fifowrite(struct knote *kn, long hint)
        soassertlocked(so);
 
        kn->kn_data = sbspace(so, &so->so_snd);
-       if (so->so_state & SS_CANTSENDMORE) {
+       if (so->so_snd.sb_state & SS_CANTSENDMORE) {
                kn->kn_flags |= EV_EOF;
                rv = 1;
        } else {
index 4f06bc5..9ce6f05 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tcp_usrreq.c,v 1.214 2022/12/12 08:30:22 tb Exp $     */
+/*     $OpenBSD: tcp_usrreq.c,v 1.215 2023/01/21 11:23:24 mvs Exp $    */
 /*     $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
 
 /*
@@ -773,7 +773,7 @@ tcp_shutdown(struct socket *so)
                ostate = tp->t_state;
        }
 
-       if (so->so_state & SS_CANTSENDMORE)
+       if (so->so_snd.sb_state & SS_CANTSENDMORE)
                goto out;
 
        socantsendmore(so);
index 8696eca..659a226 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: socketvar.h,v 1.114 2022/12/12 08:30:22 tb Exp $      */
+/*     $OpenBSD: socketvar.h,v 1.115 2023/01/21 11:23:24 mvs Exp $     */
 /*     $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $  */
 
 /*-
@@ -121,6 +121,7 @@ struct socket {
                short   sb_flags;       /* flags, see below */
 /* End area that is zeroed on flush. */
 #define        sb_endzero      sb_flags
+               short   sb_state;       /* socket state on sockbuf */
                uint64_t sb_timeo_nsecs;/* timeout for read/write */
                struct  selinfo sb_sel; /* process selecting read/write */
        } so_rcv, so_snd;
@@ -141,7 +142,13 @@ struct socket {
 
 /*
  * Socket state bits.
+ *
+ * NOTE: The following states should be used with corresponding socket's
+ * buffer `sb_state' only:
+ *
+ *     SS_CANTSENDMORE         with `so_snd' 
  */
+
 #define        SS_NOFDREF              0x001   /* no file table ref any more */
 #define        SS_ISCONNECTED          0x002   /* socket connected to a peer */
 #define        SS_ISCONNECTING         0x004   /* in process of connecting to peer */
@@ -237,7 +244,7 @@ sowriteable(struct socket *so)
        return ((sbspace(so, &so->so_snd) >= so->so_snd.sb_lowat &&
            ((so->so_state & SS_ISCONNECTED) ||
            (so->so_proto->pr_flags & PR_CONNREQUIRED)==0)) ||
-           (so->so_state & SS_CANTSENDMORE) || so->so_error);
+           (so->so_snd.sb_state & SS_CANTSENDMORE) || so->so_error);
 }
 
 /* adjust counters in sb reflecting allocation of m */