Add vsock_pending_to_accept() to move a socket directly from the
pending list to the accept queue in a single operation, avoiding
the sock_put/sock_hold dance and the sk_acceptq_removed()/
sk_acceptq_added() pair that would otherwise be needed when
calling vsock_remove_pending() followed by vsock_enqueue_accept().

Use it in vmci_transport_recv_connecting_server() where a completed
handshake transitions the socket from pending to accept queue.

Suggested-by: Stefano Garzarella <[email protected]>
Signed-off-by: Raf Dickson <[email protected]>
---
 include/net/af_vsock.h         |  1 +
 net/vmw_vsock/af_vsock.c       | 10 ++++++++++
 net/vmw_vsock/vmci_transport.c |  3 +--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 4e40063ada..30046a3c20 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -220,6 +220,7 @@ static inline bool __vsock_in_connected_table(struct 
vsock_sock *vsk)
 void vsock_add_pending(struct sock *listener, struct sock *pending);
 void vsock_remove_pending(struct sock *listener, struct sock *pending);
 void vsock_enqueue_accept(struct sock *listener, struct sock *connected);
+void vsock_pending_to_accept(struct sock *listener, struct sock *pending);
 void vsock_insert_connected(struct vsock_sock *vsk);
 void vsock_remove_bound(struct vsock_sock *vsk);
 void vsock_remove_connected(struct vsock_sock *vsk);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 2ce1063d4a..1f94f0d44c 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -496,6 +496,16 @@ void vsock_remove_pending(struct sock *listener, struct 
sock *pending)
 }
 EXPORT_SYMBOL_GPL(vsock_remove_pending);
 
+void vsock_pending_to_accept(struct sock *listener, struct sock *pending)
+{
+       struct vsock_sock *vpending = vsock_sk(pending);
+       struct vsock_sock *vlistener = vsock_sk(listener);
+
+       list_del_init(&vpending->pending_links);
+       list_add_tail(&vpending->accept_queue, &vlistener->accept_queue);
+}
+EXPORT_SYMBOL_GPL(vsock_pending_to_accept);
+
 void vsock_enqueue_accept(struct sock *listener, struct sock *connected)
 {
        struct vsock_sock *vlistener;
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 91516488a7..635ebf9da4 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -1258,8 +1258,7 @@ vmci_transport_recv_connecting_server(struct sock 
*listener,
         * listener's pending list to the accept queue so callers of accept()
         * can find it.
         */
-       vsock_remove_pending(listener, pending);
-       vsock_enqueue_accept(listener, pending);
+       vsock_pending_to_accept(listener, pending);
 
        /* Callers of accept() will be waiting on the listening socket, not
         * the pending socket.
-- 
2.54.0


Reply via email to