svn commit: r262915 - in head/sys: kern sys
Alan Somers
asomers at FreeBSD.org
Fri Mar 7 23:40:37 UTC 2014
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. */
More information about the svn-src-all
mailing list