af_unix: Try not to hold unix_gc_lock during accept().
Commit dcf70df204 ("af_unix: Fix up unix_edge.successor for embryo
socket.") added spin_lock(&unix_gc_lock) in accept() path, and it
caused regression in a stress test as reported by kernel test robot.
If the embryo socket is not part of the inflight graph, we need not
hold the lock.
To decide that in O(1) time and avoid the regression in the normal
use case,
1. add a new stat unix_sk(sk)->scm_stat.nr_unix_fds
2. count the number of inflight AF_UNIX sockets in the receive
queue under unix_state_lock()
3. move unix_update_edges() call under unix_state_lock()
4. avoid locking if nr_unix_fds is 0 in unix_update_edges()
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202404101427.92a08551-oliver.sang@intel.com
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20240413021928.20946-1-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
e918c7bbc0
commit
fd86344823
@@ -1719,12 +1719,12 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||
}
|
||||
|
||||
tsk = skb->sk;
|
||||
unix_update_edges(unix_sk(tsk));
|
||||
skb_free_datagram(sk, skb);
|
||||
wake_up_interruptible(&unix_sk(sk)->peer_wait);
|
||||
|
||||
/* attach accepted sock to socket */
|
||||
unix_state_lock(tsk);
|
||||
unix_update_edges(unix_sk(tsk));
|
||||
newsock->state = SS_CONNECTED;
|
||||
unix_sock_inherit_flags(sock, newsock);
|
||||
sock_graft(tsk, newsock);
|
||||
|
||||
Reference in New Issue
Block a user