aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-09-15 00:04:31 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-16 01:06:05 -0400
commit95ae6b228f814fc0528d0506ee9f18ac333d6851 (patch)
treed5287f3dee478e1bd5fa79e63192447c5bc91e92
parent9e0064a5456fd75fd7c70f6f3692c7f732f91a65 (diff)
ipv4: ip_ptr cleanups
dev->ip_ptr is protected by rtnl and rcu. Yet some places dont use appropriate primitives and/or locking rules. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/plip.c8
-rw-r--r--drivers/net/via-velocity.h11
-rw-r--r--drivers/net/wan/hdlc_cisco.c4
-rw-r--r--include/linux/inetdevice.h14
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--net/core/dev.c2
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/mac80211/main.c2
9 files changed, 27 insertions, 22 deletions
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 7e82a82422cf..ca4df7f4cf21 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -995,8 +995,10 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
995static void 995static void
996plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth) 996plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
997{ 997{
998 const struct in_device *in_dev = dev->ip_ptr; 998 const struct in_device *in_dev;
999 999
1000 rcu_read_lock();
1001 in_dev = __in_dev_get_rcu(dev);
1000 if (in_dev) { 1002 if (in_dev) {
1001 /* Any address will do - we take the first */ 1003 /* Any address will do - we take the first */
1002 const struct in_ifaddr *ifa = in_dev->ifa_list; 1004 const struct in_ifaddr *ifa = in_dev->ifa_list;
@@ -1006,6 +1008,7 @@ plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
1006 memcpy(eth->h_dest+2, &ifa->ifa_address, 4); 1008 memcpy(eth->h_dest+2, &ifa->ifa_address, 4);
1007 } 1009 }
1008 } 1010 }
1011 rcu_read_unlock();
1009} 1012}
1010 1013
1011static int 1014static int
@@ -1088,7 +1091,8 @@ plip_open(struct net_device *dev)
1088 when the device address isn't identical to the address of a 1091 when the device address isn't identical to the address of a
1089 received frame, the kernel incorrectly drops it). */ 1092 received frame, the kernel incorrectly drops it). */
1090 1093
1091 if ((in_dev=dev->ip_ptr) != NULL) { 1094 in_dev=__in_dev_get_rtnl(dev);
1095 if (in_dev) {
1092 /* Any address will do - we take the first. We already 1096 /* Any address will do - we take the first. We already
1093 have the first two bytes filled with 0xfc, from 1097 have the first two bytes filled with 0xfc, from
1094 plip_init_dev(). */ 1098 plip_init_dev(). */
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index f7b33ae7a703..b5e120b0074b 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -1504,22 +1504,25 @@ struct velocity_info {
1504 * addresses on this chain then we use the first - multi-IP WOL is not 1504 * addresses on this chain then we use the first - multi-IP WOL is not
1505 * supported. 1505 * supported.
1506 * 1506 *
1507 * CHECK ME: locking
1508 */ 1507 */
1509 1508
1510static inline int velocity_get_ip(struct velocity_info *vptr) 1509static inline int velocity_get_ip(struct velocity_info *vptr)
1511{ 1510{
1512 struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr; 1511 struct in_device *in_dev;
1513 struct in_ifaddr *ifa; 1512 struct in_ifaddr *ifa;
1513 int res = -ENOENT;
1514 1514
1515 rcu_read_lock();
1516 in_dev = __in_dev_get_rcu(vptr->dev);
1515 if (in_dev != NULL) { 1517 if (in_dev != NULL) {
1516 ifa = (struct in_ifaddr *) in_dev->ifa_list; 1518 ifa = (struct in_ifaddr *) in_dev->ifa_list;
1517 if (ifa != NULL) { 1519 if (ifa != NULL) {
1518 memcpy(vptr->ip_addr, &ifa->ifa_address, 4); 1520 memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
1519 return 0; 1521 res = 0;
1520 } 1522 }
1521 } 1523 }
1522 return -ENOENT; 1524 rcu_read_unlock();
1525 return res;
1523} 1526}
1524 1527
1525/** 1528/**
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b38ffa149aba..b1e5e5b69c2a 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -191,7 +191,8 @@ static int cisco_rx(struct sk_buff *skb)
191 191
192 switch (ntohl (cisco_data->type)) { 192 switch (ntohl (cisco_data->type)) {
193 case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ 193 case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
194 in_dev = dev->ip_ptr; 194 rcu_read_lock();
195 in_dev = __in_dev_get_rcu(dev);
195 addr = 0; 196 addr = 0;
196 mask = ~cpu_to_be32(0); /* is the mask correct? */ 197 mask = ~cpu_to_be32(0); /* is the mask correct? */
197 198
@@ -211,6 +212,7 @@ static int cisco_rx(struct sk_buff *skb)
211 cisco_keepalive_send(dev, CISCO_ADDR_REPLY, 212 cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
212 addr, mask); 213 addr, mask);
213 } 214 }
215 rcu_read_unlock();
214 dev_kfree_skb_any(skb); 216 dev_kfree_skb_any(skb);
215 return NET_RX_SUCCESS; 217 return NET_RX_SUCCESS;
216 218
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 2be1a1a2beb9..1ec09bb4a3ab 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -9,6 +9,7 @@
9#include <linux/rcupdate.h> 9#include <linux/rcupdate.h>
10#include <linux/timer.h> 10#include <linux/timer.h>
11#include <linux/sysctl.h> 11#include <linux/sysctl.h>
12#include <linux/rtnetlink.h>
12 13
13enum 14enum
14{ 15{
@@ -198,14 +199,10 @@ static __inline__ int bad_mask(__be32 mask, __be32 addr)
198 199
199static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev) 200static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev)
200{ 201{
201 struct in_device *in_dev = dev->ip_ptr; 202 return rcu_dereference(dev->ip_ptr);
202 if (in_dev)
203 in_dev = rcu_dereference(in_dev);
204 return in_dev;
205} 203}
206 204
207static __inline__ struct in_device * 205static inline struct in_device *in_dev_get(const struct net_device *dev)
208in_dev_get(const struct net_device *dev)
209{ 206{
210 struct in_device *in_dev; 207 struct in_device *in_dev;
211 208
@@ -217,10 +214,9 @@ in_dev_get(const struct net_device *dev)
217 return in_dev; 214 return in_dev;
218} 215}
219 216
220static __inline__ struct in_device * 217static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
221__in_dev_get_rtnl(const struct net_device *dev)
222{ 218{
223 return (struct in_device*)dev->ip_ptr; 219 return rcu_dereference_check(dev->ip_ptr, lockdep_rtnl_is_held());
224} 220}
225 221
226extern void in_dev_finish_destroy(struct in_device *idev); 222extern void in_dev_finish_destroy(struct in_device *idev);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index af05186d5b36..8992fffb8104 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -942,7 +942,7 @@ struct net_device {
942 void *dsa_ptr; /* dsa specific data */ 942 void *dsa_ptr; /* dsa specific data */
943#endif 943#endif
944 void *atalk_ptr; /* AppleTalk link */ 944 void *atalk_ptr; /* AppleTalk link */
945 void *ip_ptr; /* IPv4 specific data */ 945 struct in_device __rcu *ip_ptr; /* IPv4 specific data */
946 void *dn_ptr; /* DECnet specific data */ 946 void *dn_ptr; /* DECnet specific data */
947 void *ip6_ptr; /* IPv6 specific data */ 947 void *ip6_ptr; /* IPv6 specific data */
948 void *ec_ptr; /* Econet specific data */ 948 void *ec_ptr; /* Econet specific data */
diff --git a/net/core/dev.c b/net/core/dev.c
index fc2dc933bee5..5bdce97b8175 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5286,7 +5286,7 @@ void netdev_run_todo(void)
5286 5286
5287 /* paranoia */ 5287 /* paranoia */
5288 BUG_ON(atomic_read(&dev->refcnt)); 5288 BUG_ON(atomic_read(&dev->refcnt));
5289 WARN_ON(dev->ip_ptr); 5289 WARN_ON(rcu_dereference_raw(dev->ip_ptr));
5290 WARN_ON(dev->ip6_ptr); 5290 WARN_ON(dev->ip6_ptr);
5291 WARN_ON(dev->dn_ptr); 5291 WARN_ON(dev->dn_ptr);
5292 5292
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index da14c49284f4..c2ff48fa18c7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -209,7 +209,7 @@ static void inetdev_destroy(struct in_device *in_dev)
209 inet_free_ifa(ifa); 209 inet_free_ifa(ifa);
210 } 210 }
211 211
212 dev->ip_ptr = NULL; 212 rcu_assign_pointer(dev->ip_ptr, NULL);
213 213
214 devinet_sysctl_unregister(in_dev); 214 devinet_sysctl_unregister(in_dev);
215 neigh_parms_release(&arp_tbl, in_dev->arp_parms); 215 neigh_parms_release(&arp_tbl, in_dev->arp_parms);
@@ -1059,7 +1059,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
1059 switch (event) { 1059 switch (event) {
1060 case NETDEV_REGISTER: 1060 case NETDEV_REGISTER:
1061 printk(KERN_DEBUG "inetdev_event: bug\n"); 1061 printk(KERN_DEBUG "inetdev_event: bug\n");
1062 dev->ip_ptr = NULL; 1062 rcu_assign_pointer(dev->ip_ptr, NULL);
1063 break; 1063 break;
1064 case NETDEV_UP: 1064 case NETDEV_UP:
1065 if (!inetdev_valid_mtu(dev->mtu)) 1065 if (!inetdev_valid_mtu(dev->mtu))
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 179fcab866fc..10b24c02deb0 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -724,7 +724,7 @@ static int vif_add(struct net *net, struct mr_table *mrt,
724 case 0: 724 case 0:
725 if (vifc->vifc_flags == VIFF_USE_IFINDEX) { 725 if (vifc->vifc_flags == VIFF_USE_IFINDEX) {
726 dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex); 726 dev = dev_get_by_index(net, vifc->vifc_lcl_ifindex);
727 if (dev && dev->ip_ptr == NULL) { 727 if (dev && __in_dev_get_rtnl(dev) == NULL) {
728 dev_put(dev); 728 dev_put(dev);
729 return -EADDRNOTAVAIL; 729 return -EADDRNOTAVAIL;
730 } 730 }
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4935b843bcca..b8cf2821f00d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -362,7 +362,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
362 if (sdata->vif.type != NL80211_IFTYPE_STATION) 362 if (sdata->vif.type != NL80211_IFTYPE_STATION)
363 return NOTIFY_DONE; 363 return NOTIFY_DONE;
364 364
365 idev = sdata->dev->ip_ptr; 365 idev = __in_dev_get_rtnl(sdata->dev);
366 if (!idev) 366 if (!idev)
367 return NOTIFY_DONE; 367 return NOTIFY_DONE;
368 368