Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Dumazet and committed by
David S. Miller
fc766e4c e4a7b93b

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