diff options
| author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-12-04 20:23:53 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-12-08 13:07:24 -0500 |
| commit | 941666c2e3e0f9f6a1cb5808d02352d445bd702c (patch) | |
| tree | 389a773580ef22908391cc71f98982b03de62804 /net/core | |
| parent | a2d4b65d477aad1fe8c7218781a031fa9cf5abfc (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/core')
| -rw-r--r-- | net/core/dev.c | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index ee605c0867e7..822b15b8d11c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -743,34 +743,31 @@ struct net_device *dev_get_by_index(struct net *net, int ifindex) | |||
| 743 | EXPORT_SYMBOL(dev_get_by_index); | 743 | EXPORT_SYMBOL(dev_get_by_index); |
| 744 | 744 | ||
| 745 | /** | 745 | /** |
| 746 | * dev_getbyhwaddr - find a device by its hardware address | 746 | * dev_getbyhwaddr_rcu - find a device by its hardware address |
| 747 | * @net: the applicable net namespace | 747 | * @net: the applicable net namespace |
| 748 | * @type: media type of device | 748 | * @type: media type of device |
| 749 | * @ha: hardware address | 749 | * @ha: hardware address |
| 750 | * | 750 | * |
| 751 | * Search for an interface by MAC address. Returns NULL if the device | 751 | * Search for an interface by MAC address. Returns NULL if the device |
| 752 | * is not found or a pointer to the device. The caller must hold the | 752 | * is not found or a pointer to the device. The caller must hold RCU |
| 753 | * rtnl semaphore. The returned device has not had its ref count increased | 753 | * The returned device has not had its ref count increased |
| 754 | * and the caller must therefore be careful about locking | 754 | * and the caller must therefore be careful about locking |
| 755 | * | 755 | * |
| 756 | * BUGS: | ||
| 757 | * If the API was consistent this would be __dev_get_by_hwaddr | ||
| 758 | */ | 756 | */ |
| 759 | 757 | ||
| 760 | struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, char *ha) | 758 | struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, |
| 759 | const char *ha) | ||
| 761 | { | 760 | { |
| 762 | struct net_device *dev; | 761 | struct net_device *dev; |
| 763 | 762 | ||
| 764 | ASSERT_RTNL(); | 763 | for_each_netdev_rcu(net, dev) |
| 765 | |||
| 766 | for_each_netdev(net, dev) | ||
| 767 | if (dev->type == type && | 764 | if (dev->type == type && |
| 768 | !memcmp(dev->dev_addr, ha, dev->addr_len)) | 765 | !memcmp(dev->dev_addr, ha, dev->addr_len)) |
| 769 | return dev; | 766 | return dev; |
| 770 | 767 | ||
| 771 | return NULL; | 768 | return NULL; |
| 772 | } | 769 | } |
| 773 | EXPORT_SYMBOL(dev_getbyhwaddr); | 770 | EXPORT_SYMBOL(dev_getbyhwaddr_rcu); |
| 774 | 771 | ||
| 775 | struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type) | 772 | struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type) |
| 776 | { | 773 | { |
