Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Mar 2014 23:40:36 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262915 - in head/sys: kern sys
Message-ID:  <201403072340.s27Neabh011069@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403072340.s27Neabh011069>