Author: glebius
Date: Sun Nov 30 13:43:52 2014
New Revision: 275333
URL: https://svnweb.freebsd.org/changeset/base/275333

Log:
  Merge from projects/sendfile:
  
  - Provide pru_ready function for TCP.
  - Don't call tcp_output() from tcp_usr_send() if no ready data was put
    into the socket buffer.
  - In case of dropped connection don't try to m_freem() not ready data.
  
  Sponsored by: Nginx, Inc.
  Sponsored by: Netflix

Modified:
  head/sys/netinet/tcp_usrreq.c

Modified: head/sys/netinet/tcp_usrreq.c
==============================================================================
--- head/sys/netinet/tcp_usrreq.c       Sun Nov 30 13:40:58 2014        
(r275332)
+++ head/sys/netinet/tcp_usrreq.c       Sun Nov 30 13:43:52 2014        
(r275333)
@@ -821,7 +821,11 @@ tcp_usr_send(struct socket *so, int flag
        if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
                if (control)
                        m_freem(control);
-               if (m)
+               /*
+                * In case of PRUS_NOTREADY, tcp_usr_ready() is responsible
+                * for freeing memory.
+                */
+               if (m && (flags & PRUS_NOTREADY) == 0)
                        m_freem(m);
                error = ECONNRESET;
                goto out;
@@ -875,7 +879,8 @@ tcp_usr_send(struct socket *so, int flag
                        socantsendmore(so);
                        tcp_usrclosed(tp);
                }
-               if (!(inp->inp_flags & INP_DROPPED)) {
+               if (!(inp->inp_flags & INP_DROPPED) &&
+                   !(flags & PRUS_NOTREADY)) {
                        if (flags & PRUS_MORETOCOME)
                                tp->t_flags |= TF_MORETOCOME;
                        error = tcp_output(tp);
@@ -926,9 +931,11 @@ tcp_usr_send(struct socket *so, int flag
                        tcp_mss(tp, -1);
                }
                tp->snd_up = tp->snd_una + sbavail(&so->so_snd);
-               tp->t_flags |= TF_FORCEDATA;
-               error = tcp_output(tp);
-               tp->t_flags &= ~TF_FORCEDATA;
+               if (!(flags & PRUS_NOTREADY)) {
+                       tp->t_flags |= TF_FORCEDATA;
+                       error = tcp_output(tp);
+                       tp->t_flags &= ~TF_FORCEDATA;
+               }
        }
 out:
        TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
@@ -939,6 +946,33 @@ out:
        return (error);
 }
 
+static int
+tcp_usr_ready(struct socket *so, struct mbuf *m, int count)
+{
+       struct inpcb *inp;
+       struct tcpcb *tp;
+       int error;
+
+       inp = sotoinpcb(so);
+       INP_WLOCK(inp);
+       if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+               INP_WUNLOCK(inp);
+               for (int i = 0; i < count; i++)
+                       m = m_free(m);
+               return (ECONNRESET);
+       }
+       tp = intotcpcb(inp);
+
+       SOCKBUF_LOCK(&so->so_snd);
+       error = sbready(&so->so_snd, m, count);
+       SOCKBUF_UNLOCK(&so->so_snd);
+       if (error == 0)
+               error = tcp_output(tp);
+       INP_WUNLOCK(inp);
+
+       return (error);
+}
+
 /*
  * Abort the TCP.  Drop the connection abruptly.
  */
@@ -1073,6 +1107,7 @@ struct pr_usrreqs tcp_usrreqs = {
        .pru_rcvd =             tcp_usr_rcvd,
        .pru_rcvoob =           tcp_usr_rcvoob,
        .pru_send =             tcp_usr_send,
+       .pru_ready =            tcp_usr_ready,
        .pru_shutdown =         tcp_usr_shutdown,
        .pru_sockaddr =         in_getsockaddr,
        .pru_sosetlabel =       in_pcbsosetlabel,
@@ -1095,6 +1130,7 @@ struct pr_usrreqs tcp6_usrreqs = {
        .pru_rcvd =             tcp_usr_rcvd,
        .pru_rcvoob =           tcp_usr_rcvoob,
        .pru_send =             tcp_usr_send,
+       .pru_ready =            tcp_usr_ready,
        .pru_shutdown =         tcp_usr_shutdown,
        .pru_sockaddr =         in6_mapped_sockaddr,
        .pru_sosetlabel =       in_pcbsosetlabel,
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to