git: accept: Save foreign address earlier, if protocol supports it
Sepherosa Ziehau
sephe at crater.dragonflybsd.org
Tue Nov 29 06:16:34 PST 2011
commit 88da6203404cc737cdbc49d09c95a3ea552ef7e3
Author: Sepherosa Ziehau <sephe at 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
More information about the Commits
mailing list