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

Commit 44f4d5a2 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont Committed by David S. Miller
Browse files

Phonet: convert bound sockets hash list to RCU



This gets rid of the last spinlock in the Phonet stack proper.

Signed-off-by: default avatarRémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fce55922
Loading
Loading
Loading
Loading
+21 −24
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock)

static struct  {
	struct hlist_head hlist[PN_HASHSIZE];
	spinlock_t lock;
	struct mutex lock;
} pnsocks;

void __init pn_sock_init(void)
@@ -61,7 +61,7 @@ void __init pn_sock_init(void)

	for (i = 0; i < PN_HASHSIZE; i++)
		INIT_HLIST_HEAD(pnsocks.hlist + i);
	spin_lock_init(&pnsocks.lock);
	mutex_init(&pnsocks.lock);
}

static struct hlist_head *pn_hash_list(u16 obj)
@@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
	u8 res = spn->spn_resource;
	struct hlist_head *hlist = pn_hash_list(obj);

	spin_lock_bh(&pnsocks.lock);

	sk_for_each(sknode, node, hlist) {
	rcu_read_lock();
	sk_for_each_rcu(sknode, node, hlist) {
		struct pn_sock *pn = pn_sk(sknode);
		BUG_ON(!pn->sobject); /* unbound socket */

@@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
		sock_hold(sknode);
		break;
	}

	spin_unlock_bh(&pnsocks.lock);
	rcu_read_unlock();

	return rval;
}
@@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
	struct hlist_head *hlist = pnsocks.hlist;
	unsigned h;

	spin_lock(&pnsocks.lock);
	rcu_read_lock();
	for (h = 0; h < PN_HASHSIZE; h++) {
		struct hlist_node *node;
		struct sock *sknode;
@@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb)
		}
		hlist++;
	}
	spin_unlock(&pnsocks.lock);
	rcu_read_unlock();
}

void pn_sock_hash(struct sock *sk)
{
	struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject);

	spin_lock_bh(&pnsocks.lock);
	sk_add_node(sk, hlist);
	spin_unlock_bh(&pnsocks.lock);
	mutex_lock(&pnsocks.lock);
	sk_add_node_rcu(sk, hlist);
	mutex_unlock(&pnsocks.lock);
}
EXPORT_SYMBOL(pn_sock_hash);

void pn_sock_unhash(struct sock *sk)
{
	spin_lock_bh(&pnsocks.lock);
	sk_del_node_init(sk);
	spin_unlock_bh(&pnsocks.lock);
	mutex_lock(&pnsocks.lock);
	sk_del_node_init_rcu(sk);
	mutex_unlock(&pnsocks.lock);
	pn_sock_unbind_all_res(sk);
	synchronize_rcu();
}
EXPORT_SYMBOL(pn_sock_unhash);

@@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
	unsigned h;

	for (h = 0; h < PN_HASHSIZE; h++) {
		sk_for_each(sknode, node, hlist) {
		sk_for_each_rcu(sknode, node, hlist) {
			if (!net_eq(net, sock_net(sknode)))
				continue;
			if (!pos)
@@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk)
}

static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(pnsocks.lock)
	__acquires(rcu)
{
	spin_lock_bh(&pnsocks.lock);
	rcu_read_lock();
	return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}

@@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos)
}

static void pn_sock_seq_stop(struct seq_file *seq, void *v)
	__releases(pnsocks.lock)
	__releases(rcu)
{
	spin_unlock_bh(&pnsocks.lock);
	rcu_read_unlock();
}

static int pn_sock_seq_show(struct seq_file *seq, void *v)
@@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk)
	}
	mutex_unlock(&resource_mutex);

	if (match == 0)
		return;
	synchronize_rcu();
	while (match > 0) {
		sock_put(sk);
		__sock_put(sk);
		match--;
	}
	/* Caller is responsible for RCU sync before final sock_put() */
}

#ifdef CONFIG_PROC_FS