RDMA/addr: Use appropriate locking with for_each_netdev()
authorEric Dumazet <eric.dumazet@gmail.com>
Wed, 18 Nov 2009 22:24:34 +0000 (14:24 -0800)
committerRoland Dreier <rolandd@cisco.com>
Wed, 18 Nov 2009 22:24:34 +0000 (14:24 -0800)
for_each_netdev() should be used with RTNL or dev_base_lock held,
or else we risk a crash.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/core/addr.c

index bd07803..373f111 100644 (file)
@@ -131,6 +131,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
+               read_lock(&dev_base_lock);
                for_each_netdev(&init_net, dev) {
                        if (ipv6_chk_addr(&init_net,
                                          &((struct sockaddr_in6 *) addr)->sin6_addr,
@@ -139,6 +140,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
                                break;
                        }
                }
+               read_unlock(&dev_base_lock);
                break;
 #endif
        }
@@ -391,14 +393,17 @@ static int addr_resolve_local(struct sockaddr *src_in,
        {
                struct in6_addr *a;
 
+               read_lock(&dev_base_lock);
                for_each_netdev(&init_net, dev)
                        if (ipv6_chk_addr(&init_net,
                                          &((struct sockaddr_in6 *) dst_in)->sin6_addr,
                                          dev, 1))
                                break;
 
-               if (!dev)
+               if (!dev) {
+                       read_unlock(&dev_base_lock);
                        return -EADDRNOTAVAIL;
+               }
 
                a = &((struct sockaddr_in6 *) src_in)->sin6_addr;
 
@@ -416,6 +421,7 @@ static int addr_resolve_local(struct sockaddr *src_in,
                        if (!ret)
                                memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
                }
+               read_unlock(&dev_base_lock);
                break;
        }
 #endif