Author: asomers
Date: Fri Mar  7 23:40:36 2014
New Revision: 262915
URL: http://svnweb.freebsd.org/changeset/base/262915

Log:
  Partial revert of change 262914.  I screwed up subversion syntax with
  perforce syntax and committed some unrelated files.  Only devd files
  should've been committed.
  
  Reported by:  imp
  Pointy hat to:        asomers
  MFC after:    3 weeks
  X-MFC-With:   r262914

Modified:
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/sockbuf.h
  head/sys/sys/unpcb.h

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c Fri Mar  7 23:30:48 2014        (r262914)
+++ head/sys/kern/uipc_usrreq.c Fri Mar  7 23:40:36 2014        (r262915)
@@ -51,6 +51,7 @@
  *
  * TODO:
  *     RDM
+ *     distinguish datagram size limits from flow control limits in SEQPACKET
  *     rethink name space problems
  *     need a proper out-of-band
  */
@@ -788,6 +789,7 @@ uipc_rcvd(struct socket *so, int flags)
        struct unpcb *unp, *unp2;
        struct socket *so2;
        u_int mbcnt, sbcc;
+       u_long newhiwat;
 
        unp = sotounpcb(so);
        KASSERT(unp != NULL, ("uipc_rcvd: unp == NULL"));
@@ -809,15 +811,6 @@ uipc_rcvd(struct socket *so, int flags)
        mbcnt = so->so_rcv.sb_mbcnt;
        sbcc = so->so_rcv.sb_cc;
        SOCKBUF_UNLOCK(&so->so_rcv);
-       /*
-        * There is a benign race condition at this point.  If we're planning to
-        * clear SB_STOP, but uipc_send is called on the connected socket at
-        * this instant, it might add data to the sockbuf and set SB_STOP.  Then
-        * we would erroneously clear SB_STOP below, even though the sockbuf is
-        * full.  The race is benign because the only ill effect is to allow the
-        * sockbuf to exceed its size limit, and the size limits are not
-        * strictly guaranteed anyway.
-        */
        UNP_PCB_LOCK(unp);
        unp2 = unp->unp_conn;
        if (unp2 == NULL) {
@@ -826,9 +819,13 @@ uipc_rcvd(struct socket *so, int flags)
        }
        so2 = unp2->unp_socket;
        SOCKBUF_LOCK(&so2->so_snd);
-       if (sbcc < so2->so_snd.sb_hiwat && mbcnt < so2->so_snd.sb_mbmax)
-               so2->so_snd.sb_flags &= ~SB_STOP;
+       so2->so_snd.sb_mbmax += unp->unp_mbcnt - mbcnt;
+       newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - sbcc;
+       (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
+           newhiwat, RLIM_INFINITY);
        sowwakeup_locked(so2);
+       unp->unp_mbcnt = mbcnt;
+       unp->unp_cc = sbcc;
        UNP_PCB_UNLOCK(unp);
        return (0);
 }
@@ -839,7 +836,8 @@ uipc_send(struct socket *so, int flags, 
 {
        struct unpcb *unp, *unp2;
        struct socket *so2;
-       u_int mbcnt, sbcc;
+       u_int mbcnt_delta, sbcc;
+       u_int newhiwat;
        int error = 0;
 
        unp = sotounpcb(so);
@@ -993,21 +991,27 @@ uipc_send(struct socket *so, int flags, 
                        }
                }
 
-               mbcnt = so2->so_rcv.sb_mbcnt;
+               /*
+                * XXXRW: While fine for SOCK_STREAM, this conflates maximum
+                * datagram size and back-pressure for SOCK_SEQPACKET, which
+                * can lead to undesired return of EMSGSIZE on send instead
+                * of more desirable blocking.
+                */
+               mbcnt_delta = so2->so_rcv.sb_mbcnt - unp2->unp_mbcnt;
+               unp2->unp_mbcnt = so2->so_rcv.sb_mbcnt;
                sbcc = so2->so_rcv.sb_cc;
                sorwakeup_locked(so2);
 
-               /* 
-                * The PCB lock on unp2 protects the SB_STOP flag.  Without it,
-                * it would be possible for uipc_rcvd to be called at this
-                * point, drain the receiving sockbuf, clear SB_STOP, and then
-                * we would set SB_STOP below.  That could lead to an empty
-                * sockbuf having SB_STOP set
-                */
                SOCKBUF_LOCK(&so->so_snd);
-               if (sbcc >= so->so_snd.sb_hiwat || mbcnt >= so->so_snd.sb_mbmax)
-                       so->so_snd.sb_flags |= SB_STOP;
+               if ((int)so->so_snd.sb_hiwat >= (int)(sbcc - unp2->unp_cc))
+                       newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
+               else
+                       newhiwat = 0;
+               (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
+                   newhiwat, RLIM_INFINITY);
+               so->so_snd.sb_mbmax -= mbcnt_delta;
                SOCKBUF_UNLOCK(&so->so_snd);
+               unp2->unp_cc = sbcc;
                UNP_PCB_UNLOCK(unp2);
                m = NULL;
                break;
@@ -1045,18 +1049,27 @@ release:
 static int
 uipc_sense(struct socket *so, struct stat *sb)
 {
-       struct unpcb *unp;
+       struct unpcb *unp, *unp2;
+       struct socket *so2;
 
        unp = sotounpcb(so);
        KASSERT(unp != NULL, ("uipc_sense: unp == NULL"));
 
        sb->st_blksize = so->so_snd.sb_hiwat;
+       UNP_LINK_RLOCK();
        UNP_PCB_LOCK(unp);
+       unp2 = unp->unp_conn;
+       if ((so->so_type == SOCK_STREAM || so->so_type == SOCK_SEQPACKET) &&
+           unp2 != NULL) {
+               so2 = unp2->unp_socket;
+               sb->st_blksize += so2->so_rcv.sb_cc;
+       }
        sb->st_dev = NODEV;
        if (unp->unp_ino == 0)
                unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino;
        sb->st_ino = unp->unp_ino;
        UNP_PCB_UNLOCK(unp);
+       UNP_LINK_RUNLOCK();
        return (0);
 }
 
@@ -2484,7 +2497,8 @@ DB_SHOW_COMMAND(unpcb, db_show_unpcb)
        /* XXXRW: Would be nice to print the full address, if any. */
        db_printf("unp_addr: %p\n", unp->unp_addr);
 
-       db_printf("unp_gencnt: %llu\n",
+       db_printf("unp_cc: %d   unp_mbcnt: %d   unp_gencnt: %llu\n",
+           unp->unp_cc, unp->unp_mbcnt,
            (unsigned long long)unp->unp_gencnt);
 
        db_printf("unp_flags: %x (", unp->unp_flags);

Modified: head/sys/sys/sockbuf.h
==============================================================================
--- head/sys/sys/sockbuf.h      Fri Mar  7 23:30:48 2014        (r262914)
+++ head/sys/sys/sockbuf.h      Fri Mar  7 23:40:36 2014        (r262915)
@@ -52,7 +52,6 @@
 #define        SB_NOCOALESCE   0x200           /* don't coalesce new data into 
existing mbufs */
 #define        SB_IN_TOE       0x400           /* socket buffer is in the 
middle of an operation */
 #define        SB_AUTOSIZE     0x800           /* automatically size socket 
buffer */
-#define        SB_STOP         0x1000          /* backpressure indicator */
 
 #define        SBS_CANTSENDMORE        0x0010  /* can't send more data to peer 
*/
 #define        SBS_CANTRCVMORE         0x0020  /* can't receive more data from 
peer */
@@ -169,19 +168,9 @@ void       sbunlock(struct sockbuf *sb);
  * still be negative (cc > hiwat or mbcnt > mbmax).  Should detect
  * overflow and return 0.  Should use "lmin" but it doesn't exist now.
  */
-static __inline
-long
-sbspace(struct sockbuf *sb)
-{
-       long bleft;
-       long mleft;
-
-       if (sb->sb_flags & SB_STOP)
-               return(0);
-       bleft = sb->sb_hiwat - sb->sb_cc;
-       mleft = sb->sb_mbmax - sb->sb_mbcnt;
-       return((bleft < mleft) ? bleft : mleft);
-}
+#define        sbspace(sb) \
+    ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \
+        (int)((sb)->sb_mbmax - (sb)->sb_mbcnt)))
 
 /* adjust counters in sb reflecting allocation of m */
 #define        sballoc(sb, m) { \

Modified: head/sys/sys/unpcb.h
==============================================================================
--- head/sys/sys/unpcb.h        Fri Mar  7 23:30:48 2014        (r262914)
+++ head/sys/sys/unpcb.h        Fri Mar  7 23:40:36 2014        (r262915)
@@ -74,8 +74,8 @@ struct unpcb {
        struct  unp_head unp_refs;      /* referencing socket linked list */
        LIST_ENTRY(unpcb) unp_reflink;  /* link in unp_refs list */
        struct  sockaddr_un *unp_addr;  /* bound address of socket */
-       int     reserved1;
-       int     reserved2;
+       int     unp_cc;                 /* copy of rcv.sb_cc */
+       int     unp_mbcnt;              /* copy of rcv.sb_mbcnt */
        unp_gen_t unp_gencnt;           /* generation count of this instance */
        short   unp_flags;              /* flags */
        short   unp_gcflag;             /* Garbage collector flags. */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to