Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8063c4d6 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: qrtr: Make qrtr_port_lookup() use RCU"

parents c4152458 8757d5ff
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/qrtr.h>
#include <linux/termios.h>	/* For TIOCINQ/OUTQ */
#include <linux/numa.h>
#include <linux/spinlock.h>
#include <linux/wait.h>

#include <net/sock.h>
@@ -98,10 +99,11 @@ static inline struct qrtr_sock *qrtr_sk(struct sock *sk)
static unsigned int qrtr_local_nid = NUMA_NO_NODE;

/* for node ids */
static RADIX_TREE(qrtr_nodes, GFP_KERNEL);
static RADIX_TREE(qrtr_nodes, GFP_ATOMIC);
static DEFINE_SPINLOCK(qrtr_nodes_lock);
/* broadcast list */
static LIST_HEAD(qrtr_all_nodes);
/* lock for qrtr_nodes, qrtr_all_nodes and node reference */
/* lock for qrtr_all_nodes and node reference */
static DEFINE_MUTEX(qrtr_node_lock);

/* local port allocation management */
@@ -165,10 +167,13 @@ static void __qrtr_node_release(struct kref *kref)
{
	struct radix_tree_iter iter;
	struct qrtr_node *node = container_of(kref, struct qrtr_node, ref);
	unsigned long flags;
	void __rcu **slot;

	spin_lock_irqsave(&qrtr_nodes_lock, flags);
	if (node->nid != QRTR_EP_NID_AUTO)
		radix_tree_delete(&qrtr_nodes, node->nid);
	spin_unlock_irqrestore(&qrtr_nodes_lock, flags);

	list_del(&node->item);
	mutex_unlock(&qrtr_node_lock);
@@ -376,11 +381,12 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
static struct qrtr_node *qrtr_node_lookup(unsigned int nid)
{
	struct qrtr_node *node;
	unsigned long flags;

	mutex_lock(&qrtr_node_lock);
	spin_lock_irqsave(&qrtr_nodes_lock, flags);
	node = radix_tree_lookup(&qrtr_nodes, nid);
	node = qrtr_node_acquire(node);
	mutex_unlock(&qrtr_node_lock);
	spin_unlock_irqrestore(&qrtr_nodes_lock, flags);

	return node;
}
@@ -392,13 +398,15 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid)
 */
static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid)
{
	unsigned long flags;

	if (node->nid != QRTR_EP_NID_AUTO || nid == QRTR_EP_NID_AUTO)
		return;

	mutex_lock(&qrtr_node_lock);
	spin_lock_irqsave(&qrtr_nodes_lock, flags);
	radix_tree_insert(&qrtr_nodes, nid, node);
	node->nid = nid;
	mutex_unlock(&qrtr_node_lock);
	spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
}

/**
@@ -631,11 +639,11 @@ static struct qrtr_sock *qrtr_port_lookup(int port)
	if (port == QRTR_PORT_CTRL)
		port = 0;

	mutex_lock(&qrtr_port_lock);
	rcu_read_lock();
	ipc = idr_find(&qrtr_ports, port);
	if (ipc)
		sock_hold(&ipc->sk);
	mutex_unlock(&qrtr_port_lock);
	rcu_read_unlock();

	return ipc;
}
@@ -677,6 +685,10 @@ static void qrtr_port_remove(struct qrtr_sock *ipc)
	mutex_lock(&qrtr_port_lock);
	idr_remove(&qrtr_ports, port);
	mutex_unlock(&qrtr_port_lock);

	/* Ensure that if qrtr_port_lookup() did enter the RCU read section we
	 * wait for it to up increment the refcount */
	synchronize_rcu();
}

/* Assign port number to socket.