From ed4fba13e929b27cbaf988c177d206e99d23170e Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 11 Oct 2022 13:33:45 -0700 Subject: [PATCH] net: qrtr: Remove rcu logic for port lookup/remove synchronize_rcu() is slow and can create delays on creating/removing sockets. Some clients have latency requirements for spinning off a thread that creates a client and lookup sockets for some sessions. They close the lookup socket during this sequence which causes delays. Each call to synchronize_rcu takes 20-40 ms which is too long. Remove the rcu logic and change qrtr_port_lock to a spinlock so it can be used in qrtr_port_lookup which may be used in atomic context. Change-Id: I3244e31d3ca0599df794d3936033735bcdd3e972 Signed-off-by: Jay Jayanna Signed-off-by: Chris Lew --- net/qrtr/af_qrtr.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 43f94ea02ee9..8b0201b62f41 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -123,6 +123,7 @@ static DECLARE_RWSEM(qrtr_epts_lock); /* local port allocation management */ static DEFINE_XARRAY_ALLOC(qrtr_ports); u32 qrtr_ports_next = QRTR_MIN_EPH_SOCKET; +static DEFINE_SPINLOCK(qrtr_port_lock); /** * struct qrtr_node - endpoint node @@ -764,15 +765,16 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_unregister); static struct qrtr_sock *qrtr_port_lookup(int port) { struct qrtr_sock *ipc; + unsigned long flags; if (port == QRTR_PORT_CTRL) port = 0; - rcu_read_lock(); + spin_lock_irqsave(&qrtr_port_lock, flags); ipc = xa_load(&qrtr_ports, port); if (ipc) sock_hold(&ipc->sk); - rcu_read_unlock(); + spin_unlock_irqrestore(&qrtr_port_lock, flags); return ipc; } @@ -834,6 +836,7 @@ static void qrtr_send_del_client(struct qrtr_sock *ipc) static void qrtr_port_remove(struct qrtr_sock *ipc) { int port = ipc->us.sq_port; + unsigned long flags; qrtr_send_del_client(ipc); @@ -842,11 +845,9 @@ static void qrtr_port_remove(struct qrtr_sock *ipc) __sock_put(&ipc->sk); + spin_lock_irqsave(&qrtr_port_lock, flags); xa_erase(&qrtr_ports, port); - - /* Ensure that if qrtr_port_lookup() did enter the RCU read section we - * wait for it to up increment the refcount */ - synchronize_rcu(); + spin_unlock_irqrestore(&qrtr_port_lock, flags); } /* Assign port number to socket. @@ -913,6 +914,7 @@ static int __qrtr_bind(struct socket *sock, { struct qrtr_sock *ipc = qrtr_sk(sock->sk); struct sock *sk = sock->sk; + unsigned long flags; int port; int rc; @@ -920,10 +922,17 @@ static int __qrtr_bind(struct socket *sock, if (!zapped && addr->sq_port == ipc->us.sq_port) return 0; + spin_lock_irqsave(&qrtr_port_lock, flags); port = addr->sq_port; rc = qrtr_port_assign(ipc, &port); - if (rc) + if (rc) { + spin_unlock_irqrestore(&qrtr_port_lock, flags); return rc; + } + + if (port == QRTR_PORT_CTRL) + qrtr_reset_ports(); + spin_unlock_irqrestore(&qrtr_port_lock, flags); /* unbind previous, if any */ if (!zapped) @@ -932,10 +941,6 @@ static int __qrtr_bind(struct socket *sock, sock_reset_flag(sk, SOCK_ZAPPED); - /* Notify all open ports about the new controller */ - if (port == QRTR_PORT_CTRL) - qrtr_reset_ports(); - return 0; }