aboutsummaryrefslogtreecommitdiffstats
path: root/net/llc/af_llc.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-12-04 20:23:53 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-08 13:07:24 -0500
commit941666c2e3e0f9f6a1cb5808d02352d445bd702c (patch)
tree389a773580ef22908391cc71f98982b03de62804 /net/llc/af_llc.c
parenta2d4b65d477aad1fe8c7218781a031fa9cf5abfc (diff)
net: RCU conversion of dev_getbyhwaddr() and arp_ioctl()
Le dimanche 05 décembre 2010 à 09:19 +0100, Eric Dumazet a écrit : > Hmm.. > > If somebody can explain why RTNL is held in arp_ioctl() (and therefore > in arp_req_delete()), we might first remove RTNL use in arp_ioctl() so > that your patch can be applied. > > Right now it is not good, because RTNL wont be necessarly held when you > are going to call arp_invalidate() ? While doing this analysis, I found a refcount bug in llc, I'll send a patch for net-2.6 Meanwhile, here is the patch for net-next-2.6 Your patch then can be applied after mine. Thanks [PATCH] net: RCU conversion of dev_getbyhwaddr() and arp_ioctl() dev_getbyhwaddr() was called under RTNL. Rename it to dev_getbyhwaddr_rcu() and change all its caller to now use RCU locking instead of RTNL. Change arp_ioctl() to use RCU instead of RTNL locking. Note: this fix a dev refcount bug in llc Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/llc/af_llc.c')
-rw-r--r--net/llc/af_llc.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 582612998211..dfd3a648a551 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -316,9 +316,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
316 if (unlikely(addr->sllc_family != AF_LLC)) 316 if (unlikely(addr->sllc_family != AF_LLC))
317 goto out; 317 goto out;
318 rc = -ENODEV; 318 rc = -ENODEV;
319 rtnl_lock(); 319 rcu_read_lock();
320 if (sk->sk_bound_dev_if) { 320 if (sk->sk_bound_dev_if) {
321 llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); 321 llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
322 if (llc->dev) { 322 if (llc->dev) {
323 if (!addr->sllc_arphrd) 323 if (!addr->sllc_arphrd)
324 addr->sllc_arphrd = llc->dev->type; 324 addr->sllc_arphrd = llc->dev->type;
@@ -329,14 +329,15 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
329 !llc_mac_match(addr->sllc_mac, 329 !llc_mac_match(addr->sllc_mac,
330 llc->dev->dev_addr)) { 330 llc->dev->dev_addr)) {
331 rc = -EINVAL; 331 rc = -EINVAL;
332 dev_put(llc->dev);
333 llc->dev = NULL; 332 llc->dev = NULL;
334 } 333 }
335 } 334 }
336 } else 335 } else
337 llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, 336 llc->dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd,
338 addr->sllc_mac); 337 addr->sllc_mac);
339 rtnl_unlock(); 338 if (llc->dev)
339 dev_hold(llc->dev);
340 rcu_read_unlock();
340 if (!llc->dev) 341 if (!llc->dev)
341 goto out; 342 goto out;
342 if (!addr->sllc_sap) { 343 if (!addr->sllc_sap) {