Commit fc766e4c4965915ab52a1d1fa3c7a7b3e7bc07f0

Authored by Eric Dumazet
Committed by David S. Miller
1 parent e4a7b93bd5

decnet: RCU conversion and get rid of dev_base_lock

While tracking dev_base_lock users, I found decnet used it in
dnet_select_source(), but for a wrong purpose:

Writers only hold RTNL, not dev_base_lock, so readers must use RCU if
they cannot use RTNL.

Adds an rcu_head in struct dn_ifaddr and handle proper RCU management.

Adds __rcu annotation in dn_route as well.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 8 changed files with 127 additions and 88 deletions Side-by-side Diff

include/linux/netdevice.h
... ... @@ -951,7 +951,7 @@
951 951 #endif
952 952 void *atalk_ptr; /* AppleTalk link */
953 953 struct in_device __rcu *ip_ptr; /* IPv4 specific data */
954   - void *dn_ptr; /* DECnet specific data */
  954 + struct dn_dev __rcu *dn_ptr; /* DECnet specific data */
955 955 struct inet6_dev __rcu *ip6_ptr; /* IPv6 specific data */
956 956 void *ec_ptr; /* Econet specific data */
957 957 void *ax25_ptr; /* AX.25 specific data */
include/net/dn_dev.h
... ... @@ -5,13 +5,14 @@
5 5 struct dn_dev;
6 6  
7 7 struct dn_ifaddr {
8   - struct dn_ifaddr *ifa_next;
  8 + struct dn_ifaddr __rcu *ifa_next;
9 9 struct dn_dev *ifa_dev;
10 10 __le16 ifa_local;
11 11 __le16 ifa_address;
12 12 __u8 ifa_flags;
13 13 __u8 ifa_scope;
14 14 char ifa_label[IFNAMSIZ];
  15 + struct rcu_head rcu;
15 16 };
16 17  
17 18 #define DN_DEV_S_RU 0 /* Run - working normally */
... ... @@ -83,7 +84,7 @@
83 84  
84 85  
85 86 struct dn_dev {
86   - struct dn_ifaddr *ifa_list;
  87 + struct dn_ifaddr __rcu *ifa_list;
87 88 struct net_device *dev;
88 89 struct dn_dev_parms parms;
89 90 char use_long;
90 91  
91 92  
92 93  
93 94  
... ... @@ -171,19 +172,27 @@
171 172  
172 173 static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
173 174 {
174   - struct dn_dev *dn_db = dev->dn_ptr;
  175 + struct dn_dev *dn_db;
175 176 struct dn_ifaddr *ifa;
  177 + int res = 0;
176 178  
  179 + rcu_read_lock();
  180 + dn_db = rcu_dereference(dev->dn_ptr);
177 181 if (dn_db == NULL) {
178 182 printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
179   - return 0;
  183 + goto out;
180 184 }
181 185  
182   - for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next)
183   - if ((addr ^ ifa->ifa_local) == 0)
184   - return 1;
185   -
186   - return 0;
  186 + for (ifa = rcu_dereference(dn_db->ifa_list);
  187 + ifa != NULL;
  188 + ifa = rcu_dereference(ifa->ifa_next))
  189 + if ((addr ^ ifa->ifa_local) == 0) {
  190 + res = 1;
  191 + break;
  192 + }
  193 +out:
  194 + rcu_read_unlock();
  195 + return res;
187 196 }
188 197  
189 198 #endif /* _NET_DN_DEV_H */
... ... @@ -94,10 +94,10 @@
94 94 int __use;
95 95 unsigned long lastuse;
96 96 union {
97   - struct dst_entry *next;
98   - struct rtable __rcu *rt_next;
99   - struct rt6_info *rt6_next;
100   - struct dn_route *dn_next;
  97 + struct dst_entry *next;
  98 + struct rtable __rcu *rt_next;
  99 + struct rt6_info *rt6_next;
  100 + struct dn_route __rcu *dn_next;
101 101 };
102 102 };
103 103  
net/decnet/af_decnet.c
... ... @@ -1848,7 +1848,7 @@
1848 1848 {
1849 1849 unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER;
1850 1850 if (dev) {
1851   - struct dn_dev *dn_db = dev->dn_ptr;
  1851 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1852 1852 mtu -= LL_RESERVED_SPACE(dev);
1853 1853 if (dn_db->use_long)
1854 1854 mtu -= 21;
... ... @@ -267,7 +267,7 @@
267 267 if (table->extra1 == NULL)
268 268 return -EINVAL;
269 269  
270   - dn_db = dev->dn_ptr;
  270 + dn_db = rcu_dereference_raw(dev->dn_ptr);
271 271 old = dn_db->parms.forwarding;
272 272  
273 273 err = proc_dointvec(table, write, buffer, lenp, ppos);
274 274  
275 275  
276 276  
... ... @@ -332,14 +332,19 @@
332 332 return ifa;
333 333 }
334 334  
335   -static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa)
  335 +static void dn_dev_free_ifa_rcu(struct rcu_head *head)
336 336 {
337   - kfree(ifa);
  337 + kfree(container_of(head, struct dn_ifaddr, rcu));
338 338 }
339 339  
340   -static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int destroy)
  340 +static void dn_dev_free_ifa(struct dn_ifaddr *ifa)
341 341 {
342   - struct dn_ifaddr *ifa1 = *ifap;
  342 + call_rcu(&ifa->rcu, dn_dev_free_ifa_rcu);
  343 +}
  344 +
  345 +static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy)
  346 +{
  347 + struct dn_ifaddr *ifa1 = rtnl_dereference(*ifap);
343 348 unsigned char mac_addr[6];
344 349 struct net_device *dev = dn_db->dev;
345 350  
... ... @@ -373,7 +378,9 @@
373 378 ASSERT_RTNL();
374 379  
375 380 /* Check for duplicates */
376   - for(ifa1 = dn_db->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
  381 + for (ifa1 = rtnl_dereference(dn_db->ifa_list);
  382 + ifa1 != NULL;
  383 + ifa1 = rtnl_dereference(ifa1->ifa_next)) {
377 384 if (ifa1->ifa_local == ifa->ifa_local)
378 385 return -EEXIST;
379 386 }
... ... @@ -386,7 +393,7 @@
386 393 }
387 394  
388 395 ifa->ifa_next = dn_db->ifa_list;
389   - dn_db->ifa_list = ifa;
  396 + rcu_assign_pointer(dn_db->ifa_list, ifa);
390 397  
391 398 dn_ifaddr_notify(RTM_NEWADDR, ifa);
392 399 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
... ... @@ -396,7 +403,7 @@
396 403  
397 404 static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
398 405 {
399   - struct dn_dev *dn_db = dev->dn_ptr;
  406 + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
400 407 int rv;
401 408  
402 409 if (dn_db == NULL) {
... ... @@ -425,7 +432,8 @@
425 432 struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
426 433 struct dn_dev *dn_db;
427 434 struct net_device *dev;
428   - struct dn_ifaddr *ifa = NULL, **ifap = NULL;
  435 + struct dn_ifaddr *ifa = NULL;
  436 + struct dn_ifaddr __rcu **ifap = NULL;
429 437 int ret = 0;
430 438  
431 439 if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
... ... @@ -454,8 +462,10 @@
454 462 goto done;
455 463 }
456 464  
457   - if ((dn_db = dev->dn_ptr) != NULL) {
458   - for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
  465 + if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) {
  466 + for (ifap = &dn_db->ifa_list;
  467 + (ifa = rtnl_dereference(*ifap)) != NULL;
  468 + ifap = &ifa->ifa_next)
459 469 if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
460 470 break;
461 471 }
... ... @@ -558,7 +568,7 @@
558 568  
559 569 dev = __dev_get_by_index(&init_net, ifindex);
560 570 if (dev)
561   - dn_dev = dev->dn_ptr;
  571 + dn_dev = rtnl_dereference(dev->dn_ptr);
562 572  
563 573 return dn_dev;
564 574 }
... ... @@ -576,7 +586,8 @@
576 586 struct nlattr *tb[IFA_MAX+1];
577 587 struct dn_dev *dn_db;
578 588 struct ifaddrmsg *ifm;
579   - struct dn_ifaddr *ifa, **ifap;
  589 + struct dn_ifaddr *ifa;
  590 + struct dn_ifaddr __rcu **ifap;
580 591 int err = -EINVAL;
581 592  
582 593 if (!net_eq(net, &init_net))
... ... @@ -592,7 +603,9 @@
592 603 goto errout;
593 604  
594 605 err = -EADDRNOTAVAIL;
595   - for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) {
  606 + for (ifap = &dn_db->ifa_list;
  607 + (ifa = rtnl_dereference(*ifap)) != NULL;
  608 + ifap = &ifa->ifa_next) {
596 609 if (tb[IFA_LOCAL] &&
597 610 nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
598 611 continue;
... ... @@ -632,7 +645,7 @@
632 645 if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
633 646 return -ENODEV;
634 647  
635   - if ((dn_db = dev->dn_ptr) == NULL) {
  648 + if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) {
636 649 dn_db = dn_dev_create(dev, &err);
637 650 if (!dn_db)
638 651 return err;
639 652  
... ... @@ -748,11 +761,11 @@
748 761 skip_naddr = 0;
749 762 }
750 763  
751   - if ((dn_db = dev->dn_ptr) == NULL)
  764 + if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL)
752 765 goto cont;
753 766  
754   - for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
755   - ifa = ifa->ifa_next, dn_idx++) {
  767 + for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa;
  768 + ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) {
756 769 if (dn_idx < skip_naddr)
757 770 continue;
758 771  
759 772  
760 773  
761 774  
762 775  
... ... @@ -773,21 +786,22 @@
773 786  
774 787 static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
775 788 {
776   - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
  789 + struct dn_dev *dn_db;
777 790 struct dn_ifaddr *ifa;
778 791 int rv = -ENODEV;
779 792  
  793 + rcu_read_lock();
  794 + dn_db = rcu_dereference(dev->dn_ptr);
780 795 if (dn_db == NULL)
781 796 goto out;
782 797  
783   - rtnl_lock();
784   - ifa = dn_db->ifa_list;
  798 + ifa = rcu_dereference(dn_db->ifa_list);
785 799 if (ifa != NULL) {
786 800 *addr = ifa->ifa_local;
787 801 rv = 0;
788 802 }
789   - rtnl_unlock();
790 803 out:
  804 + rcu_read_unlock();
791 805 return rv;
792 806 }
793 807  
... ... @@ -823,7 +837,7 @@
823 837 struct endnode_hello_message *msg;
824 838 struct sk_buff *skb = NULL;
825 839 __le16 *pktlen;
826   - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
  840 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
827 841  
828 842 if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
829 843 return;
... ... @@ -889,7 +903,7 @@
889 903 static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
890 904 {
891 905 int n;
892   - struct dn_dev *dn_db = dev->dn_ptr;
  906 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
893 907 struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
894 908 struct sk_buff *skb;
895 909 size_t size;
... ... @@ -960,7 +974,7 @@
960 974  
961 975 static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
962 976 {
963   - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
  977 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
964 978  
965 979 if (dn_db->parms.forwarding == 0)
966 980 dn_send_endnode_hello(dev, ifa);
... ... @@ -998,7 +1012,7 @@
998 1012  
999 1013 static int dn_eth_up(struct net_device *dev)
1000 1014 {
1001   - struct dn_dev *dn_db = dev->dn_ptr;
  1015 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1002 1016  
1003 1017 if (dn_db->parms.forwarding == 0)
1004 1018 dev_mc_add(dev, dn_rt_all_end_mcast);
... ... @@ -1012,7 +1026,7 @@
1012 1026  
1013 1027 static void dn_eth_down(struct net_device *dev)
1014 1028 {
1015   - struct dn_dev *dn_db = dev->dn_ptr;
  1029 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1016 1030  
1017 1031 if (dn_db->parms.forwarding == 0)
1018 1032 dev_mc_del(dev, dn_rt_all_end_mcast);
1019 1033  
1020 1034  
... ... @@ -1025,12 +1039,16 @@
1025 1039 static void dn_dev_timer_func(unsigned long arg)
1026 1040 {
1027 1041 struct net_device *dev = (struct net_device *)arg;
1028   - struct dn_dev *dn_db = dev->dn_ptr;
  1042 + struct dn_dev *dn_db;
1029 1043 struct dn_ifaddr *ifa;
1030 1044  
  1045 + rcu_read_lock();
  1046 + dn_db = rcu_dereference(dev->dn_ptr);
1031 1047 if (dn_db->t3 <= dn_db->parms.t2) {
1032 1048 if (dn_db->parms.timer3) {
1033   - for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {
  1049 + for (ifa = rcu_dereference(dn_db->ifa_list);
  1050 + ifa;
  1051 + ifa = rcu_dereference(ifa->ifa_next)) {
1034 1052 if (!(ifa->ifa_flags & IFA_F_SECONDARY))
1035 1053 dn_db->parms.timer3(dev, ifa);
1036 1054 }
1037 1055  
... ... @@ -1039,13 +1057,13 @@
1039 1057 } else {
1040 1058 dn_db->t3 -= dn_db->parms.t2;
1041 1059 }
1042   -
  1060 + rcu_read_unlock();
1043 1061 dn_dev_set_timer(dev);
1044 1062 }
1045 1063  
1046 1064 static void dn_dev_set_timer(struct net_device *dev)
1047 1065 {
1048   - struct dn_dev *dn_db = dev->dn_ptr;
  1066 + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
1049 1067  
1050 1068 if (dn_db->parms.t2 > dn_db->parms.t3)
1051 1069 dn_db->parms.t2 = dn_db->parms.t3;
... ... @@ -1077,8 +1095,8 @@
1077 1095 return NULL;
1078 1096  
1079 1097 memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
1080   - smp_wmb();
1081   - dev->dn_ptr = dn_db;
  1098 +
  1099 + rcu_assign_pointer(dev->dn_ptr, dn_db);
1082 1100 dn_db->dev = dev;
1083 1101 init_timer(&dn_db->timer);
1084 1102  
... ... @@ -1086,7 +1104,7 @@
1086 1104  
1087 1105 dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
1088 1106 if (!dn_db->neigh_parms) {
1089   - dev->dn_ptr = NULL;
  1107 + rcu_assign_pointer(dev->dn_ptr, NULL);
1090 1108 kfree(dn_db);
1091 1109 return NULL;
1092 1110 }
... ... @@ -1125,7 +1143,7 @@
1125 1143 struct dn_ifaddr *ifa;
1126 1144 __le16 addr = decnet_address;
1127 1145 int maybe_default = 0;
1128   - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
  1146 + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1129 1147  
1130 1148 if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
1131 1149 return;
... ... @@ -1176,7 +1194,7 @@
1176 1194  
1177 1195 static void dn_dev_delete(struct net_device *dev)
1178 1196 {
1179   - struct dn_dev *dn_db = dev->dn_ptr;
  1197 + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1180 1198  
1181 1199 if (dn_db == NULL)
1182 1200 return;
1183 1201  
... ... @@ -1204,13 +1222,13 @@
1204 1222  
1205 1223 void dn_dev_down(struct net_device *dev)
1206 1224 {
1207   - struct dn_dev *dn_db = dev->dn_ptr;
  1225 + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
1208 1226 struct dn_ifaddr *ifa;
1209 1227  
1210 1228 if (dn_db == NULL)
1211 1229 return;
1212 1230  
1213   - while((ifa = dn_db->ifa_list) != NULL) {
  1231 + while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) {
1214 1232 dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
1215 1233 dn_dev_free_ifa(ifa);
1216 1234 }
... ... @@ -1270,7 +1288,7 @@
1270 1288 }
1271 1289  
1272 1290 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
1273   - __acquires(rcu)
  1291 + __acquires(RCU)
1274 1292 {
1275 1293 int i;
1276 1294 struct net_device *dev;
... ... @@ -1313,7 +1331,7 @@
1313 1331 }
1314 1332  
1315 1333 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
1316   - __releases(rcu)
  1334 + __releases(RCU)
1317 1335 {
1318 1336 rcu_read_unlock();
1319 1337 }
... ... @@ -1340,7 +1358,7 @@
1340 1358 struct net_device *dev = v;
1341 1359 char peer_buf[DN_ASCBUF_LEN];
1342 1360 char router_buf[DN_ASCBUF_LEN];
1343   - struct dn_dev *dn_db = dev->dn_ptr;
  1361 + struct dn_dev *dn_db = rcu_dereference(dev->dn_ptr);
1344 1362  
1345 1363 seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu"
1346 1364 " %04hu %03d %02x %-10s %-7s %-7s\n",
... ... @@ -610,10 +610,12 @@
610 610 /* Scan device list */
611 611 rcu_read_lock();
612 612 for_each_netdev_rcu(&init_net, dev) {
613   - dn_db = dev->dn_ptr;
  613 + dn_db = rcu_dereference(dev->dn_ptr);
614 614 if (dn_db == NULL)
615 615 continue;
616   - for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) {
  616 + for (ifa2 = rcu_dereference(dn_db->ifa_list);
  617 + ifa2 != NULL;
  618 + ifa2 = rcu_dereference(ifa2->ifa_next)) {
617 619 if (ifa2->ifa_local == ifa->ifa_local) {
618 620 found_it = 1;
619 621 break;
net/decnet/dn_neigh.c
... ... @@ -391,7 +391,7 @@
391 391 write_lock(&neigh->lock);
392 392  
393 393 neigh->used = jiffies;
394   - dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
  394 + dn_db = rcu_dereference(neigh->dev->dn_ptr);
395 395  
396 396 if (!(neigh->nud_state & NUD_PERMANENT)) {
397 397 neigh->updated = jiffies;
net/decnet/dn_route.c
... ... @@ -93,7 +93,7 @@
93 93  
94 94 struct dn_rt_hash_bucket
95 95 {
96   - struct dn_route *chain;
  96 + struct dn_route __rcu *chain;
97 97 spinlock_t lock;
98 98 };
99 99  
100 100  
101 101  
... ... @@ -157,15 +157,17 @@
157 157 static void dn_dst_check_expire(unsigned long dummy)
158 158 {
159 159 int i;
160   - struct dn_route *rt, **rtp;
  160 + struct dn_route *rt;
  161 + struct dn_route __rcu **rtp;
161 162 unsigned long now = jiffies;
162 163 unsigned long expire = 120 * HZ;
163 164  
164   - for(i = 0; i <= dn_rt_hash_mask; i++) {
  165 + for (i = 0; i <= dn_rt_hash_mask; i++) {
165 166 rtp = &dn_rt_hash_table[i].chain;
166 167  
167 168 spin_lock(&dn_rt_hash_table[i].lock);
168   - while((rt=*rtp) != NULL) {
  169 + while ((rt = rcu_dereference_protected(*rtp,
  170 + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
169 171 if (atomic_read(&rt->dst.__refcnt) ||
170 172 (now - rt->dst.lastuse) < expire) {
171 173 rtp = &rt->dst.dn_next;
172 174  
173 175  
... ... @@ -186,17 +188,19 @@
186 188  
187 189 static int dn_dst_gc(struct dst_ops *ops)
188 190 {
189   - struct dn_route *rt, **rtp;
  191 + struct dn_route *rt;
  192 + struct dn_route __rcu **rtp;
190 193 int i;
191 194 unsigned long now = jiffies;
192 195 unsigned long expire = 10 * HZ;
193 196  
194   - for(i = 0; i <= dn_rt_hash_mask; i++) {
  197 + for (i = 0; i <= dn_rt_hash_mask; i++) {
195 198  
196 199 spin_lock_bh(&dn_rt_hash_table[i].lock);
197 200 rtp = &dn_rt_hash_table[i].chain;
198 201  
199   - while((rt=*rtp) != NULL) {
  202 + while ((rt = rcu_dereference_protected(*rtp,
  203 + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
200 204 if (atomic_read(&rt->dst.__refcnt) ||
201 205 (now - rt->dst.lastuse) < expire) {
202 206 rtp = &rt->dst.dn_next;
... ... @@ -227,7 +231,7 @@
227 231 {
228 232 u32 min_mtu = 230;
229 233 struct dn_dev *dn = dst->neighbour ?
230   - (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL;
  234 + rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL;
231 235  
232 236 if (dn && dn->use_long == 0)
233 237 min_mtu -= 6;
234 238  
... ... @@ -277,13 +281,15 @@
277 281  
278 282 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
279 283 {
280   - struct dn_route *rth, **rthp;
  284 + struct dn_route *rth;
  285 + struct dn_route __rcu **rthp;
281 286 unsigned long now = jiffies;
282 287  
283 288 rthp = &dn_rt_hash_table[hash].chain;
284 289  
285 290 spin_lock_bh(&dn_rt_hash_table[hash].lock);
286   - while((rth = *rthp) != NULL) {
  291 + while ((rth = rcu_dereference_protected(*rthp,
  292 + lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) {
287 293 if (compare_keys(&rth->fl, &rt->fl)) {
288 294 /* Put it first */
289 295 *rthp = rth->dst.dn_next;
290 296  
291 297  
... ... @@ -315,15 +321,15 @@
315 321 int i;
316 322 struct dn_route *rt, *next;
317 323  
318   - for(i = 0; i < dn_rt_hash_mask; i++) {
  324 + for (i = 0; i < dn_rt_hash_mask; i++) {
319 325 spin_lock_bh(&dn_rt_hash_table[i].lock);
320 326  
321   - if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL)
  327 + if ((rt = xchg((struct dn_route **)&dn_rt_hash_table[i].chain, NULL)) == NULL)
322 328 goto nothing_to_declare;
323 329  
324   - for(; rt; rt=next) {
325   - next = rt->dst.dn_next;
326   - rt->dst.dn_next = NULL;
  330 + for(; rt; rt = next) {
  331 + next = rcu_dereference_raw(rt->dst.dn_next);
  332 + RCU_INIT_POINTER(rt->dst.dn_next, NULL);
327 333 dst_free((struct dst_entry *)rt);
328 334 }
329 335  
330 336  
331 337  
... ... @@ -458,15 +464,16 @@
458 464 */
459 465 static int dn_route_rx_packet(struct sk_buff *skb)
460 466 {
461   - struct dn_skb_cb *cb = DN_SKB_CB(skb);
  467 + struct dn_skb_cb *cb;
462 468 int err;
463 469  
464 470 if ((err = dn_route_input(skb)) == 0)
465 471 return dst_input(skb);
466 472  
  473 + cb = DN_SKB_CB(skb);
467 474 if (decnet_debug_level & 4) {
468 475 char *devname = skb->dev ? skb->dev->name : "???";
469   - struct dn_skb_cb *cb = DN_SKB_CB(skb);
  476 +
470 477 printk(KERN_DEBUG
471 478 "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
472 479 (int)cb->rt_flags, devname, skb->len,
... ... @@ -573,7 +580,7 @@
573 580 struct dn_skb_cb *cb;
574 581 unsigned char flags = 0;
575 582 __u16 len = le16_to_cpu(*(__le16 *)skb->data);
576   - struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
  583 + struct dn_dev *dn = rcu_dereference(dev->dn_ptr);
577 584 unsigned char padlen = 0;
578 585  
579 586 if (!net_eq(dev_net(dev), &init_net))
... ... @@ -728,7 +735,7 @@
728 735 {
729 736 struct dn_skb_cb *cb = DN_SKB_CB(skb);
730 737 struct dst_entry *dst = skb_dst(skb);
731   - struct dn_dev *dn_db = dst->dev->dn_ptr;
  738 + struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
732 739 struct dn_route *rt;
733 740 struct neighbour *neigh = dst->neighbour;
734 741 int header_len;
735 742  
... ... @@ -835,13 +842,16 @@
835 842 static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope)
836 843 {
837 844 __le16 saddr = 0;
838   - struct dn_dev *dn_db = dev->dn_ptr;
  845 + struct dn_dev *dn_db;
839 846 struct dn_ifaddr *ifa;
840 847 int best_match = 0;
841 848 int ret;
842 849  
843   - read_lock(&dev_base_lock);
844   - for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) {
  850 + rcu_read_lock();
  851 + dn_db = rcu_dereference(dev->dn_ptr);
  852 + for (ifa = rcu_dereference(dn_db->ifa_list);
  853 + ifa != NULL;
  854 + ifa = rcu_dereference(ifa->ifa_next)) {
845 855 if (ifa->ifa_scope > scope)
846 856 continue;
847 857 if (!daddr) {
... ... @@ -854,7 +864,7 @@
854 864 if (best_match == 0)
855 865 saddr = ifa->ifa_local;
856 866 }
857   - read_unlock(&dev_base_lock);
  867 + rcu_read_unlock();
858 868  
859 869 return saddr;
860 870 }
... ... @@ -1020,7 +1030,7 @@
1020 1030 err = -ENODEV;
1021 1031 if (dev_out == NULL)
1022 1032 goto out;
1023   - dn_db = dev_out->dn_ptr;
  1033 + dn_db = rcu_dereference_raw(dev_out->dn_ptr);
1024 1034 /* Possible improvement - check all devices for local addr */
1025 1035 if (dn_dev_islocal(dev_out, fl.fld_dst)) {
1026 1036 dev_put(dev_out);
... ... @@ -1233,7 +1243,7 @@
1233 1243  
1234 1244 dev_hold(in_dev);
1235 1245  
1236   - if ((dn_db = in_dev->dn_ptr) == NULL)
  1246 + if ((dn_db = rcu_dereference(in_dev->dn_ptr)) == NULL)
1237 1247 goto out;
1238 1248  
1239 1249 /* Zero source addresses are not allowed */
1240 1250  
1241 1251  
... ... @@ -1677,15 +1687,15 @@
1677 1687 {
1678 1688 struct dn_rt_cache_iter_state *s = seq->private;
1679 1689  
1680   - rt = rt->dst.dn_next;
1681   - while(!rt) {
  1690 + rt = rcu_dereference_bh(rt->dst.dn_next);
  1691 + while (!rt) {
1682 1692 rcu_read_unlock_bh();
1683 1693 if (--s->bucket < 0)
1684 1694 break;
1685 1695 rcu_read_lock_bh();
1686   - rt = dn_rt_hash_table[s->bucket].chain;
  1696 + rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain);
1687 1697 }
1688   - return rcu_dereference_bh(rt);
  1698 + return rt;
1689 1699 }
1690 1700  
1691 1701 static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos)