net: introduce netif_addr_lock_nested() and call if when appropriate
authorJiri Pirko <jpirko@redhat.com>
Mon, 9 Jan 2012 06:36:54 +0000 (06:36 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 9 Jan 2012 20:46:58 +0000 (12:46 -0800)
dev_uc_sync() and dev_mc_sync() are acquiring netif_addr_lock for
destination device of synchronization. Since netif_addr_lock is
already held at the time for source device, this triggers lockdep
deadlock warning.

There's no way this deadlock can happen so use spin_lock_nested() to
silence the warning.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/core/dev_addr_lists.c

index a1d109590da4b429d81ba02e62e00cec620bf06f..d0522bb2d4a01af23976642a5fb93eac0f75873d 100644 (file)
@@ -2450,6 +2450,11 @@ static inline void netif_addr_lock(struct net_device *dev)
        spin_lock(&dev->addr_list_lock);
 }
 
+static inline void netif_addr_lock_nested(struct net_device *dev)
+{
+       spin_lock_nested(&dev->addr_list_lock, SINGLE_DEPTH_NESTING);
+}
+
 static inline void netif_addr_lock_bh(struct net_device *dev)
 {
        spin_lock_bh(&dev->addr_list_lock);
index c34ce9f9c9761c5ad9fd27f8e1ec8e409bb9afe3..29c07fef922847aaabf4cd24c91f91d477c4edc0 100644 (file)
@@ -439,11 +439,11 @@ int dev_uc_sync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_bh(to);
+       netif_addr_lock_nested(to);
        err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
-       netif_addr_unlock_bh(to);
+       netif_addr_unlock(to);
        return err;
 }
 EXPORT_SYMBOL(dev_uc_sync);
@@ -463,7 +463,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
                return;
 
        netif_addr_lock_bh(from);
-       netif_addr_lock(to);
+       netif_addr_lock_nested(to);
        __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
        __dev_set_rx_mode(to);
        netif_addr_unlock(to);
@@ -602,11 +602,11 @@ int dev_mc_sync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_bh(to);
+       netif_addr_lock_nested(to);
        err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
-       netif_addr_unlock_bh(to);
+       netif_addr_unlock(to);
        return err;
 }
 EXPORT_SYMBOL(dev_mc_sync);
@@ -626,7 +626,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
                return;
 
        netif_addr_lock_bh(from);
-       netif_addr_lock(to);
+       netif_addr_lock_nested(to);
        __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
        __dev_set_rx_mode(to);
        netif_addr_unlock(to);