DragonFly BSD
DragonFly commits List (threaded) for 2011-11
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

git: accept: Save foreign address earlier, if protocol supports it


From: Sepherosa Ziehau <sephe@xxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 29 Nov 2011 06:14:54 -0800 (PST)

commit 88da6203404cc737cdbc49d09c95a3ea552ef7e3
Author: Sepherosa Ziehau <sephe@dragonflybsd.org>
Date:   Tue Nov 29 21:38:34 2011 +0800

    accept: Save foreign address earlier, if protocol supports it
    
    - Add so_faddr into socket, which records the accepted socket's foreign
      address.  If it is set, kern_accept() will use it directly instead of
      calling protocol specific method to extract the foreign address.
    - Add protocol specific method, pru_safefaddr, which will save the
      foreign address into socket.so_faddr if the necessary information is
      supplied.  This protocol method will only be called in protocol
      thread.
    - Pass the foreign address to sonewconn() if possible, so the foreign
      address could be saved before the accepted socket is put onto the
      complete list.
    
    Currently only IPv4/TCP implemented pru_savefaddr
    
    This intends to address the following problems:
    - Calling pru_accept directly from user context is not MPSAFE, we
      always races the socket.so_pcb check->use against protocol thread
      clear/free socket.so_pcb, though the race window is too tiny to
      be hit.  To make it mpsafe, we should dispatch pru_accept to
      protocol thread.
      If socket.so_faddr is set here, we are race against nothing and
      nothing expensive like put the current user thread into sleep will
      happen.  However, if the socket is dropped when it still sits
      on the complete list, the error will not be timely delivered, i.e.
      accept(2) will not return error, but the later on read(2)/write(2)
      on the socket will deliver the error.
    - Calling pru_accept directly races against the inpcb.inp_f{addr,port}
      setting up in the protocol thread, since inpcb.inp_f{addr,port} is
      setup _after_ the accepted socket was put onto the complete list.
    
         user thread                  proto thread
              :                             :
              :                  accepted socket -> comp
              :             (inpcb.inp_f{addr,port} are 0 here)
        comp -> socket                      :
         pru_accept                         :
              :                setup inpcb.inp_f{addr,port}
    
      Returning of 0.0.0.0:0 from accept(2) was observed on heavily loaded
      web servers.

Summary of changes:
 sys/kern/uipc_socket.c     |   14 +++++++++++---
 sys/kern/uipc_socket2.c    |   16 +++++++++++++++-
 sys/kern/uipc_syscalls.c   |   10 +++++++++-
 sys/netinet/in_pcb.c       |   17 +++++++++++++++++
 sys/netinet/in_pcb.h       |    1 +
 sys/netinet/tcp_syncache.c |   25 +++++++++++++++++--------
 sys/netinet/tcp_usrreq.c   |    9 ++++++++-
 sys/sys/protosw.h          |    7 +++++++
 sys/sys/socketvar.h        |    4 ++++
 9 files changed, 89 insertions(+), 14 deletions(-)

http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/88da6203404cc737cdbc49d09c95a3ea552ef7e3


-- 
DragonFly BSD source repository



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]