There is a long-standing race with listen(2) in that it does not
properly interlock with concurrent I/O on the socket. Becuase listen(2)
destroys the socket buffers, such a race can trigger panics. In
practice this does not arise since applications have no reason to
trigger the race. However, it needs to be fixed.
Part of the problem is that there is no good way to reliably check
whether a socket is a listening socket, except by locking the socket and
checking SOLISTENING(so). However, the socket lock is generally not
used during I/O, and it is undesirable to incur the overhead of
acquiring it just to check for a condition that should never occur,
modulo application bugs or malicious behaviour.
listen(2) calls are relatively rare. Thus, the strategy is to have it
acquire all socket buffer locks when transitioning to a listening
socket. To do this safely, these locks must be stable, and not
destroyed during listen(2) as they are today. So, move them out of the
sockbuf and into the owning socket. For the sockbuf mutexes, keep a
pointer to the mutex in the sockbuf itself, for now.
The change manages to avoid bloating the size of struct socket. The
slab efficiency is the same as before: 4 sockets per page on LP64
systems.