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 <jayanna@codeaurora.org>
Signed-off-by: Chris Lew <quic_clew@quicinc.com>
This commit is contained in:
Chris Lew 2022-10-11 13:33:45 -07:00
parent 904b1aa353
commit ed4fba13e9

View File

@ -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;
}