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>