diff options
Diffstat (limited to 'net/decnet')
-rw-r--r-- | net/decnet/af_decnet.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_dev.c | 100 | ||||
-rw-r--r-- | net/decnet/dn_fib.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 2 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 137 | ||||
-rw-r--r-- | net/decnet/dn_rules.c | 2 |
6 files changed, 147 insertions, 106 deletions
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 6f97268ed85f..2af15b15d1fa 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -829,7 +829,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) | |||
829 | return -EINVAL; | 829 | return -EINVAL; |
830 | 830 | ||
831 | scp->state = DN_CC; | 831 | scp->state = DN_CC; |
832 | scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); | 832 | scp->segsize_loc = dst_metric_advmss(__sk_dst_get(sk)); |
833 | dn_send_conn_conf(sk, allocation); | 833 | dn_send_conn_conf(sk, allocation); |
834 | 834 | ||
835 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 835 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
@@ -958,7 +958,7 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen, | |||
958 | sk->sk_route_caps = sk->sk_dst_cache->dev->features; | 958 | sk->sk_route_caps = sk->sk_dst_cache->dev->features; |
959 | sock->state = SS_CONNECTING; | 959 | sock->state = SS_CONNECTING; |
960 | scp->state = DN_CI; | 960 | scp->state = DN_CI; |
961 | scp->segsize_loc = dst_metric(sk->sk_dst_cache, RTAX_ADVMSS); | 961 | scp->segsize_loc = dst_metric_advmss(sk->sk_dst_cache); |
962 | 962 | ||
963 | dn_nsp_send_conninit(sk, NSP_CI); | 963 | dn_nsp_send_conninit(sk, NSP_CI); |
964 | err = -EINPROGRESS; | 964 | err = -EINPROGRESS; |
@@ -1850,7 +1850,7 @@ unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu) | |||
1850 | { | 1850 | { |
1851 | unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER; | 1851 | unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER; |
1852 | if (dev) { | 1852 | if (dev) { |
1853 | struct dn_dev *dn_db = dev->dn_ptr; | 1853 | struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); |
1854 | mtu -= LL_RESERVED_SPACE(dev); | 1854 | mtu -= LL_RESERVED_SPACE(dev); |
1855 | if (dn_db->use_long) | 1855 | if (dn_db->use_long) |
1856 | mtu -= 21; | 1856 | mtu -= 21; |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 9b73e0b03e34..0dcaa903e00e 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -267,7 +267,7 @@ static int dn_forwarding_proc(ctl_table *table, int write, | |||
267 | if (table->extra1 == NULL) | 267 | if (table->extra1 == NULL) |
268 | return -EINVAL; | 268 | return -EINVAL; |
269 | 269 | ||
270 | dn_db = dev->dn_ptr; | 270 | dn_db = rcu_dereference_raw(dev->dn_ptr); |
271 | old = dn_db->parms.forwarding; | 271 | old = dn_db->parms.forwarding; |
272 | 272 | ||
273 | err = proc_dointvec(table, write, buffer, lenp, ppos); | 273 | err = proc_dointvec(table, write, buffer, lenp, ppos); |
@@ -332,14 +332,19 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void) | |||
332 | return ifa; | 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 | unsigned char mac_addr[6]; | 348 | unsigned char mac_addr[6]; |
344 | struct net_device *dev = dn_db->dev; | 349 | struct net_device *dev = dn_db->dev; |
345 | 350 | ||
@@ -373,7 +378,9 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
373 | ASSERT_RTNL(); | 378 | ASSERT_RTNL(); |
374 | 379 | ||
375 | /* Check for duplicates */ | 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 | if (ifa1->ifa_local == ifa->ifa_local) | 384 | if (ifa1->ifa_local == ifa->ifa_local) |
378 | return -EEXIST; | 385 | return -EEXIST; |
379 | } | 386 | } |
@@ -386,7 +393,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
386 | } | 393 | } |
387 | 394 | ||
388 | ifa->ifa_next = dn_db->ifa_list; | 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 | dn_ifaddr_notify(RTM_NEWADDR, ifa); | 398 | dn_ifaddr_notify(RTM_NEWADDR, ifa); |
392 | blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); | 399 | blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); |
@@ -396,7 +403,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
396 | 403 | ||
397 | static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa) | 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 | int rv; | 407 | int rv; |
401 | 408 | ||
402 | if (dn_db == NULL) { | 409 | if (dn_db == NULL) { |
@@ -425,7 +432,8 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) | |||
425 | struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr; | 432 | struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr; |
426 | struct dn_dev *dn_db; | 433 | struct dn_dev *dn_db; |
427 | struct net_device *dev; | 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 | int ret = 0; | 437 | int ret = 0; |
430 | 438 | ||
431 | if (copy_from_user(ifr, arg, DN_IFREQ_SIZE)) | 439 | if (copy_from_user(ifr, arg, DN_IFREQ_SIZE)) |
@@ -454,8 +462,10 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) | |||
454 | goto done; | 462 | goto done; |
455 | } | 463 | } |
456 | 464 | ||
457 | if ((dn_db = dev->dn_ptr) != NULL) { | 465 | if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) { |
458 | for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) | 466 | for (ifap = &dn_db->ifa_list; |
467 | (ifa = rtnl_dereference(*ifap)) != NULL; | ||
468 | ifap = &ifa->ifa_next) | ||
459 | if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0) | 469 | if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0) |
460 | break; | 470 | break; |
461 | } | 471 | } |
@@ -558,7 +568,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex) | |||
558 | 568 | ||
559 | dev = __dev_get_by_index(&init_net, ifindex); | 569 | dev = __dev_get_by_index(&init_net, ifindex); |
560 | if (dev) | 570 | if (dev) |
561 | dn_dev = dev->dn_ptr; | 571 | dn_dev = rtnl_dereference(dev->dn_ptr); |
562 | 572 | ||
563 | return dn_dev; | 573 | return dn_dev; |
564 | } | 574 | } |
@@ -576,7 +586,8 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
576 | struct nlattr *tb[IFA_MAX+1]; | 586 | struct nlattr *tb[IFA_MAX+1]; |
577 | struct dn_dev *dn_db; | 587 | struct dn_dev *dn_db; |
578 | struct ifaddrmsg *ifm; | 588 | struct ifaddrmsg *ifm; |
579 | struct dn_ifaddr *ifa, **ifap; | 589 | struct dn_ifaddr *ifa; |
590 | struct dn_ifaddr __rcu **ifap; | ||
580 | int err = -EINVAL; | 591 | int err = -EINVAL; |
581 | 592 | ||
582 | if (!net_eq(net, &init_net)) | 593 | if (!net_eq(net, &init_net)) |
@@ -592,7 +603,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
592 | goto errout; | 603 | goto errout; |
593 | 604 | ||
594 | err = -EADDRNOTAVAIL; | 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 | if (tb[IFA_LOCAL] && | 609 | if (tb[IFA_LOCAL] && |
597 | nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2)) | 610 | nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2)) |
598 | continue; | 611 | continue; |
@@ -632,7 +645,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
632 | if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL) | 645 | if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL) |
633 | return -ENODEV; | 646 | return -ENODEV; |
634 | 647 | ||
635 | if ((dn_db = dev->dn_ptr) == NULL) { | 648 | if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) { |
636 | dn_db = dn_dev_create(dev, &err); | 649 | dn_db = dn_dev_create(dev, &err); |
637 | if (!dn_db) | 650 | if (!dn_db) |
638 | return err; | 651 | return err; |
@@ -748,11 +761,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
748 | skip_naddr = 0; | 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 | goto cont; | 765 | goto cont; |
753 | 766 | ||
754 | for (ifa = dn_db->ifa_list, dn_idx = 0; ifa; | 767 | for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa; |
755 | ifa = ifa->ifa_next, dn_idx++) { | 768 | ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) { |
756 | if (dn_idx < skip_naddr) | 769 | if (dn_idx < skip_naddr) |
757 | continue; | 770 | continue; |
758 | 771 | ||
@@ -773,21 +786,22 @@ done: | |||
773 | 786 | ||
774 | static int dn_dev_get_first(struct net_device *dev, __le16 *addr) | 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 | struct dn_ifaddr *ifa; | 790 | struct dn_ifaddr *ifa; |
778 | int rv = -ENODEV; | 791 | int rv = -ENODEV; |
779 | 792 | ||
793 | rcu_read_lock(); | ||
794 | dn_db = rcu_dereference(dev->dn_ptr); | ||
780 | if (dn_db == NULL) | 795 | if (dn_db == NULL) |
781 | goto out; | 796 | goto out; |
782 | 797 | ||
783 | rtnl_lock(); | 798 | ifa = rcu_dereference(dn_db->ifa_list); |
784 | ifa = dn_db->ifa_list; | ||
785 | if (ifa != NULL) { | 799 | if (ifa != NULL) { |
786 | *addr = ifa->ifa_local; | 800 | *addr = ifa->ifa_local; |
787 | rv = 0; | 801 | rv = 0; |
788 | } | 802 | } |
789 | rtnl_unlock(); | ||
790 | out: | 803 | out: |
804 | rcu_read_unlock(); | ||
791 | return rv; | 805 | return rv; |
792 | } | 806 | } |
793 | 807 | ||
@@ -823,7 +837,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) | |||
823 | struct endnode_hello_message *msg; | 837 | struct endnode_hello_message *msg; |
824 | struct sk_buff *skb = NULL; | 838 | struct sk_buff *skb = NULL; |
825 | __le16 *pktlen; | 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 | if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL) | 842 | if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL) |
829 | return; | 843 | return; |
@@ -889,7 +903,7 @@ static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn | |||
889 | static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) | 903 | static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) |
890 | { | 904 | { |
891 | int n; | 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 | struct dn_neigh *dn = (struct dn_neigh *)dn_db->router; | 907 | struct dn_neigh *dn = (struct dn_neigh *)dn_db->router; |
894 | struct sk_buff *skb; | 908 | struct sk_buff *skb; |
895 | size_t size; | 909 | size_t size; |
@@ -960,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) | |||
960 | 974 | ||
961 | static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa) | 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 | if (dn_db->parms.forwarding == 0) | 979 | if (dn_db->parms.forwarding == 0) |
966 | dn_send_endnode_hello(dev, ifa); | 980 | dn_send_endnode_hello(dev, ifa); |
@@ -998,7 +1012,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) | |||
998 | 1012 | ||
999 | static int dn_eth_up(struct net_device *dev) | 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 | if (dn_db->parms.forwarding == 0) | 1017 | if (dn_db->parms.forwarding == 0) |
1004 | dev_mc_add(dev, dn_rt_all_end_mcast); | 1018 | dev_mc_add(dev, dn_rt_all_end_mcast); |
@@ -1012,7 +1026,7 @@ static int dn_eth_up(struct net_device *dev) | |||
1012 | 1026 | ||
1013 | static void dn_eth_down(struct net_device *dev) | 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 | if (dn_db->parms.forwarding == 0) | 1031 | if (dn_db->parms.forwarding == 0) |
1018 | dev_mc_del(dev, dn_rt_all_end_mcast); | 1032 | dev_mc_del(dev, dn_rt_all_end_mcast); |
@@ -1025,12 +1039,16 @@ static void dn_dev_set_timer(struct net_device *dev); | |||
1025 | static void dn_dev_timer_func(unsigned long arg) | 1039 | static void dn_dev_timer_func(unsigned long arg) |
1026 | { | 1040 | { |
1027 | struct net_device *dev = (struct net_device *)arg; | 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 | struct dn_ifaddr *ifa; | 1043 | struct dn_ifaddr *ifa; |
1030 | 1044 | ||
1045 | rcu_read_lock(); | ||
1046 | dn_db = rcu_dereference(dev->dn_ptr); | ||
1031 | if (dn_db->t3 <= dn_db->parms.t2) { | 1047 | if (dn_db->t3 <= dn_db->parms.t2) { |
1032 | if (dn_db->parms.timer3) { | 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 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) | 1052 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) |
1035 | dn_db->parms.timer3(dev, ifa); | 1053 | dn_db->parms.timer3(dev, ifa); |
1036 | } | 1054 | } |
@@ -1039,13 +1057,13 @@ static void dn_dev_timer_func(unsigned long arg) | |||
1039 | } else { | 1057 | } else { |
1040 | dn_db->t3 -= dn_db->parms.t2; | 1058 | dn_db->t3 -= dn_db->parms.t2; |
1041 | } | 1059 | } |
1042 | 1060 | rcu_read_unlock(); | |
1043 | dn_dev_set_timer(dev); | 1061 | dn_dev_set_timer(dev); |
1044 | } | 1062 | } |
1045 | 1063 | ||
1046 | static void dn_dev_set_timer(struct net_device *dev) | 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 | if (dn_db->parms.t2 > dn_db->parms.t3) | 1068 | if (dn_db->parms.t2 > dn_db->parms.t3) |
1051 | dn_db->parms.t2 = dn_db->parms.t3; | 1069 | dn_db->parms.t2 = dn_db->parms.t3; |
@@ -1077,8 +1095,8 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err) | |||
1077 | return NULL; | 1095 | return NULL; |
1078 | 1096 | ||
1079 | memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); | 1097 | memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); |
1080 | smp_wmb(); | 1098 | |
1081 | dev->dn_ptr = dn_db; | 1099 | rcu_assign_pointer(dev->dn_ptr, dn_db); |
1082 | dn_db->dev = dev; | 1100 | dn_db->dev = dev; |
1083 | init_timer(&dn_db->timer); | 1101 | init_timer(&dn_db->timer); |
1084 | 1102 | ||
@@ -1086,7 +1104,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err) | |||
1086 | 1104 | ||
1087 | dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table); | 1105 | dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table); |
1088 | if (!dn_db->neigh_parms) { | 1106 | if (!dn_db->neigh_parms) { |
1089 | dev->dn_ptr = NULL; | 1107 | rcu_assign_pointer(dev->dn_ptr, NULL); |
1090 | kfree(dn_db); | 1108 | kfree(dn_db); |
1091 | return NULL; | 1109 | return NULL; |
1092 | } | 1110 | } |
@@ -1125,7 +1143,7 @@ void dn_dev_up(struct net_device *dev) | |||
1125 | struct dn_ifaddr *ifa; | 1143 | struct dn_ifaddr *ifa; |
1126 | __le16 addr = decnet_address; | 1144 | __le16 addr = decnet_address; |
1127 | int maybe_default = 0; | 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 | if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) | 1148 | if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) |
1131 | return; | 1149 | return; |
@@ -1176,7 +1194,7 @@ void dn_dev_up(struct net_device *dev) | |||
1176 | 1194 | ||
1177 | static void dn_dev_delete(struct net_device *dev) | 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 | if (dn_db == NULL) | 1199 | if (dn_db == NULL) |
1182 | return; | 1200 | return; |
@@ -1204,13 +1222,13 @@ static void dn_dev_delete(struct net_device *dev) | |||
1204 | 1222 | ||
1205 | void dn_dev_down(struct net_device *dev) | 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 | struct dn_ifaddr *ifa; | 1226 | struct dn_ifaddr *ifa; |
1209 | 1227 | ||
1210 | if (dn_db == NULL) | 1228 | if (dn_db == NULL) |
1211 | return; | 1229 | return; |
1212 | 1230 | ||
1213 | while((ifa = dn_db->ifa_list) != NULL) { | 1231 | while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) { |
1214 | dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0); | 1232 | dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0); |
1215 | dn_dev_free_ifa(ifa); | 1233 | dn_dev_free_ifa(ifa); |
1216 | } | 1234 | } |
@@ -1270,7 +1288,7 @@ static inline int is_dn_dev(struct net_device *dev) | |||
1270 | } | 1288 | } |
1271 | 1289 | ||
1272 | static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) | 1290 | static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) |
1273 | __acquires(rcu) | 1291 | __acquires(RCU) |
1274 | { | 1292 | { |
1275 | int i; | 1293 | int i; |
1276 | struct net_device *dev; | 1294 | struct net_device *dev; |
@@ -1313,7 +1331,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
1313 | } | 1331 | } |
1314 | 1332 | ||
1315 | static void dn_dev_seq_stop(struct seq_file *seq, void *v) | 1333 | static void dn_dev_seq_stop(struct seq_file *seq, void *v) |
1316 | __releases(rcu) | 1334 | __releases(RCU) |
1317 | { | 1335 | { |
1318 | rcu_read_unlock(); | 1336 | rcu_read_unlock(); |
1319 | } | 1337 | } |
@@ -1340,7 +1358,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) | |||
1340 | struct net_device *dev = v; | 1358 | struct net_device *dev = v; |
1341 | char peer_buf[DN_ASCBUF_LEN]; | 1359 | char peer_buf[DN_ASCBUF_LEN]; |
1342 | char router_buf[DN_ASCBUF_LEN]; | 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 | seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu" | 1363 | seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu" |
1346 | " %04hu %03d %02x %-10s %-7s %-7s\n", | 1364 | " %04hu %03d %02x %-10s %-7s %-7s\n", |
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 4ab96c15166d..0ef0a81bcd72 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c | |||
@@ -610,10 +610,12 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) | |||
610 | /* Scan device list */ | 610 | /* Scan device list */ |
611 | rcu_read_lock(); | 611 | rcu_read_lock(); |
612 | for_each_netdev_rcu(&init_net, dev) { | 612 | for_each_netdev_rcu(&init_net, dev) { |
613 | dn_db = dev->dn_ptr; | 613 | dn_db = rcu_dereference(dev->dn_ptr); |
614 | if (dn_db == NULL) | 614 | if (dn_db == NULL) |
615 | continue; | 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 | if (ifa2->ifa_local == ifa->ifa_local) { | 619 | if (ifa2->ifa_local == ifa->ifa_local) { |
618 | found_it = 1; | 620 | found_it = 1; |
619 | break; | 621 | break; |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index a085dbcf5c7f..602dade7e9a3 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -391,7 +391,7 @@ int dn_neigh_router_hello(struct sk_buff *skb) | |||
391 | write_lock(&neigh->lock); | 391 | write_lock(&neigh->lock); |
392 | 392 | ||
393 | neigh->used = jiffies; | 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 | if (!(neigh->nud_state & NUD_PERMANENT)) { | 396 | if (!(neigh->nud_state & NUD_PERMANENT)) { |
397 | neigh->updated = jiffies; | 397 | neigh->updated = jiffies; |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index df0f3e54ff8a..5e636365d33c 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -93,7 +93,7 @@ | |||
93 | 93 | ||
94 | struct dn_rt_hash_bucket | 94 | struct dn_rt_hash_bucket |
95 | { | 95 | { |
96 | struct dn_route *chain; | 96 | struct dn_route __rcu *chain; |
97 | spinlock_t lock; | 97 | spinlock_t lock; |
98 | }; | 98 | }; |
99 | 99 | ||
@@ -110,6 +110,8 @@ static unsigned long dn_rt_deadline; | |||
110 | 110 | ||
111 | static int dn_dst_gc(struct dst_ops *ops); | 111 | static int dn_dst_gc(struct dst_ops *ops); |
112 | static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); | 112 | static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); |
113 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); | ||
114 | static unsigned int dn_dst_default_mtu(const struct dst_entry *dst); | ||
113 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); | 115 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); |
114 | static void dn_dst_link_failure(struct sk_buff *); | 116 | static void dn_dst_link_failure(struct sk_buff *); |
115 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); | 117 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); |
@@ -129,6 +131,8 @@ static struct dst_ops dn_dst_ops = { | |||
129 | .gc_thresh = 128, | 131 | .gc_thresh = 128, |
130 | .gc = dn_dst_gc, | 132 | .gc = dn_dst_gc, |
131 | .check = dn_dst_check, | 133 | .check = dn_dst_check, |
134 | .default_advmss = dn_dst_default_advmss, | ||
135 | .default_mtu = dn_dst_default_mtu, | ||
132 | .negative_advice = dn_dst_negative_advice, | 136 | .negative_advice = dn_dst_negative_advice, |
133 | .link_failure = dn_dst_link_failure, | 137 | .link_failure = dn_dst_link_failure, |
134 | .update_pmtu = dn_dst_update_pmtu, | 138 | .update_pmtu = dn_dst_update_pmtu, |
@@ -157,15 +161,17 @@ static inline void dnrt_drop(struct dn_route *rt) | |||
157 | static void dn_dst_check_expire(unsigned long dummy) | 161 | static void dn_dst_check_expire(unsigned long dummy) |
158 | { | 162 | { |
159 | int i; | 163 | int i; |
160 | struct dn_route *rt, **rtp; | 164 | struct dn_route *rt; |
165 | struct dn_route __rcu **rtp; | ||
161 | unsigned long now = jiffies; | 166 | unsigned long now = jiffies; |
162 | unsigned long expire = 120 * HZ; | 167 | unsigned long expire = 120 * HZ; |
163 | 168 | ||
164 | for(i = 0; i <= dn_rt_hash_mask; i++) { | 169 | for (i = 0; i <= dn_rt_hash_mask; i++) { |
165 | rtp = &dn_rt_hash_table[i].chain; | 170 | rtp = &dn_rt_hash_table[i].chain; |
166 | 171 | ||
167 | spin_lock(&dn_rt_hash_table[i].lock); | 172 | spin_lock(&dn_rt_hash_table[i].lock); |
168 | while((rt=*rtp) != NULL) { | 173 | while ((rt = rcu_dereference_protected(*rtp, |
174 | lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { | ||
169 | if (atomic_read(&rt->dst.__refcnt) || | 175 | if (atomic_read(&rt->dst.__refcnt) || |
170 | (now - rt->dst.lastuse) < expire) { | 176 | (now - rt->dst.lastuse) < expire) { |
171 | rtp = &rt->dst.dn_next; | 177 | rtp = &rt->dst.dn_next; |
@@ -186,17 +192,19 @@ static void dn_dst_check_expire(unsigned long dummy) | |||
186 | 192 | ||
187 | static int dn_dst_gc(struct dst_ops *ops) | 193 | static int dn_dst_gc(struct dst_ops *ops) |
188 | { | 194 | { |
189 | struct dn_route *rt, **rtp; | 195 | struct dn_route *rt; |
196 | struct dn_route __rcu **rtp; | ||
190 | int i; | 197 | int i; |
191 | unsigned long now = jiffies; | 198 | unsigned long now = jiffies; |
192 | unsigned long expire = 10 * HZ; | 199 | unsigned long expire = 10 * HZ; |
193 | 200 | ||
194 | for(i = 0; i <= dn_rt_hash_mask; i++) { | 201 | for (i = 0; i <= dn_rt_hash_mask; i++) { |
195 | 202 | ||
196 | spin_lock_bh(&dn_rt_hash_table[i].lock); | 203 | spin_lock_bh(&dn_rt_hash_table[i].lock); |
197 | rtp = &dn_rt_hash_table[i].chain; | 204 | rtp = &dn_rt_hash_table[i].chain; |
198 | 205 | ||
199 | while((rt=*rtp) != NULL) { | 206 | while ((rt = rcu_dereference_protected(*rtp, |
207 | lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { | ||
200 | if (atomic_read(&rt->dst.__refcnt) || | 208 | if (atomic_read(&rt->dst.__refcnt) || |
201 | (now - rt->dst.lastuse) < expire) { | 209 | (now - rt->dst.lastuse) < expire) { |
202 | rtp = &rt->dst.dn_next; | 210 | rtp = &rt->dst.dn_next; |
@@ -227,7 +235,7 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
227 | { | 235 | { |
228 | u32 min_mtu = 230; | 236 | u32 min_mtu = 230; |
229 | struct dn_dev *dn = dst->neighbour ? | 237 | struct dn_dev *dn = dst->neighbour ? |
230 | (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL; | 238 | rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL; |
231 | 239 | ||
232 | if (dn && dn->use_long == 0) | 240 | if (dn && dn->use_long == 0) |
233 | min_mtu -= 6; | 241 | min_mtu -= 6; |
@@ -236,13 +244,14 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
236 | 244 | ||
237 | if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { | 245 | if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { |
238 | if (!(dst_metric_locked(dst, RTAX_MTU))) { | 246 | if (!(dst_metric_locked(dst, RTAX_MTU))) { |
239 | dst->metrics[RTAX_MTU-1] = mtu; | 247 | dst_metric_set(dst, RTAX_MTU, mtu); |
240 | dst_set_expires(dst, dn_rt_mtu_expires); | 248 | dst_set_expires(dst, dn_rt_mtu_expires); |
241 | } | 249 | } |
242 | if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { | 250 | if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { |
243 | u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; | 251 | u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; |
244 | if (dst_metric(dst, RTAX_ADVMSS) > mss) | 252 | u32 existing_mss = dst_metric_raw(dst, RTAX_ADVMSS); |
245 | dst->metrics[RTAX_ADVMSS-1] = mss; | 253 | if (!existing_mss || existing_mss > mss) |
254 | dst_metric_set(dst, RTAX_ADVMSS, mss); | ||
246 | } | 255 | } |
247 | } | 256 | } |
248 | } | 257 | } |
@@ -267,23 +276,25 @@ static void dn_dst_link_failure(struct sk_buff *skb) | |||
267 | 276 | ||
268 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 277 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
269 | { | 278 | { |
270 | return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | | 279 | return ((fl1->fld_dst ^ fl2->fld_dst) | |
271 | (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | | 280 | (fl1->fld_src ^ fl2->fld_src) | |
272 | (fl1->mark ^ fl2->mark) | | 281 | (fl1->mark ^ fl2->mark) | |
273 | (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | | 282 | (fl1->fld_scope ^ fl2->fld_scope) | |
274 | (fl1->oif ^ fl2->oif) | | 283 | (fl1->oif ^ fl2->oif) | |
275 | (fl1->iif ^ fl2->iif)) == 0; | 284 | (fl1->iif ^ fl2->iif)) == 0; |
276 | } | 285 | } |
277 | 286 | ||
278 | static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) | 287 | static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) |
279 | { | 288 | { |
280 | struct dn_route *rth, **rthp; | 289 | struct dn_route *rth; |
290 | struct dn_route __rcu **rthp; | ||
281 | unsigned long now = jiffies; | 291 | unsigned long now = jiffies; |
282 | 292 | ||
283 | rthp = &dn_rt_hash_table[hash].chain; | 293 | rthp = &dn_rt_hash_table[hash].chain; |
284 | 294 | ||
285 | spin_lock_bh(&dn_rt_hash_table[hash].lock); | 295 | spin_lock_bh(&dn_rt_hash_table[hash].lock); |
286 | while((rth = *rthp) != NULL) { | 296 | while ((rth = rcu_dereference_protected(*rthp, |
297 | lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) { | ||
287 | if (compare_keys(&rth->fl, &rt->fl)) { | 298 | if (compare_keys(&rth->fl, &rt->fl)) { |
288 | /* Put it first */ | 299 | /* Put it first */ |
289 | *rthp = rth->dst.dn_next; | 300 | *rthp = rth->dst.dn_next; |
@@ -315,15 +326,15 @@ static void dn_run_flush(unsigned long dummy) | |||
315 | int i; | 326 | int i; |
316 | struct dn_route *rt, *next; | 327 | struct dn_route *rt, *next; |
317 | 328 | ||
318 | for(i = 0; i < dn_rt_hash_mask; i++) { | 329 | for (i = 0; i < dn_rt_hash_mask; i++) { |
319 | spin_lock_bh(&dn_rt_hash_table[i].lock); | 330 | spin_lock_bh(&dn_rt_hash_table[i].lock); |
320 | 331 | ||
321 | if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL) | 332 | if ((rt = xchg((struct dn_route **)&dn_rt_hash_table[i].chain, NULL)) == NULL) |
322 | goto nothing_to_declare; | 333 | goto nothing_to_declare; |
323 | 334 | ||
324 | for(; rt; rt=next) { | 335 | for(; rt; rt = next) { |
325 | next = rt->dst.dn_next; | 336 | next = rcu_dereference_raw(rt->dst.dn_next); |
326 | rt->dst.dn_next = NULL; | 337 | RCU_INIT_POINTER(rt->dst.dn_next, NULL); |
327 | dst_free((struct dst_entry *)rt); | 338 | dst_free((struct dst_entry *)rt); |
328 | } | 339 | } |
329 | 340 | ||
@@ -458,15 +469,16 @@ static int dn_return_long(struct sk_buff *skb) | |||
458 | */ | 469 | */ |
459 | static int dn_route_rx_packet(struct sk_buff *skb) | 470 | static int dn_route_rx_packet(struct sk_buff *skb) |
460 | { | 471 | { |
461 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | 472 | struct dn_skb_cb *cb; |
462 | int err; | 473 | int err; |
463 | 474 | ||
464 | if ((err = dn_route_input(skb)) == 0) | 475 | if ((err = dn_route_input(skb)) == 0) |
465 | return dst_input(skb); | 476 | return dst_input(skb); |
466 | 477 | ||
478 | cb = DN_SKB_CB(skb); | ||
467 | if (decnet_debug_level & 4) { | 479 | if (decnet_debug_level & 4) { |
468 | char *devname = skb->dev ? skb->dev->name : "???"; | 480 | char *devname = skb->dev ? skb->dev->name : "???"; |
469 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | 481 | |
470 | printk(KERN_DEBUG | 482 | printk(KERN_DEBUG |
471 | "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n", | 483 | "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 | (int)cb->rt_flags, devname, skb->len, | 484 | (int)cb->rt_flags, devname, skb->len, |
@@ -573,7 +585,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type | |||
573 | struct dn_skb_cb *cb; | 585 | struct dn_skb_cb *cb; |
574 | unsigned char flags = 0; | 586 | unsigned char flags = 0; |
575 | __u16 len = le16_to_cpu(*(__le16 *)skb->data); | 587 | __u16 len = le16_to_cpu(*(__le16 *)skb->data); |
576 | struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; | 588 | struct dn_dev *dn = rcu_dereference(dev->dn_ptr); |
577 | unsigned char padlen = 0; | 589 | unsigned char padlen = 0; |
578 | 590 | ||
579 | if (!net_eq(dev_net(dev), &init_net)) | 591 | if (!net_eq(dev_net(dev), &init_net)) |
@@ -728,7 +740,7 @@ static int dn_forward(struct sk_buff *skb) | |||
728 | { | 740 | { |
729 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | 741 | struct dn_skb_cb *cb = DN_SKB_CB(skb); |
730 | struct dst_entry *dst = skb_dst(skb); | 742 | struct dst_entry *dst = skb_dst(skb); |
731 | struct dn_dev *dn_db = dst->dev->dn_ptr; | 743 | struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr); |
732 | struct dn_route *rt; | 744 | struct dn_route *rt; |
733 | struct neighbour *neigh = dst->neighbour; | 745 | struct neighbour *neigh = dst->neighbour; |
734 | int header_len; | 746 | int header_len; |
@@ -788,19 +800,28 @@ static int dn_rt_bug(struct sk_buff *skb) | |||
788 | return NET_RX_DROP; | 800 | return NET_RX_DROP; |
789 | } | 801 | } |
790 | 802 | ||
803 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst) | ||
804 | { | ||
805 | return dn_mss_from_pmtu(dst->dev, dst_mtu(dst)); | ||
806 | } | ||
807 | |||
808 | static unsigned int dn_dst_default_mtu(const struct dst_entry *dst) | ||
809 | { | ||
810 | return dst->dev->mtu; | ||
811 | } | ||
812 | |||
791 | static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | 813 | static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) |
792 | { | 814 | { |
793 | struct dn_fib_info *fi = res->fi; | 815 | struct dn_fib_info *fi = res->fi; |
794 | struct net_device *dev = rt->dst.dev; | 816 | struct net_device *dev = rt->dst.dev; |
795 | struct neighbour *n; | 817 | struct neighbour *n; |
796 | unsigned mss; | 818 | unsigned int metric; |
797 | 819 | ||
798 | if (fi) { | 820 | if (fi) { |
799 | if (DN_FIB_RES_GW(*res) && | 821 | if (DN_FIB_RES_GW(*res) && |
800 | DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 822 | DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
801 | rt->rt_gateway = DN_FIB_RES_GW(*res); | 823 | rt->rt_gateway = DN_FIB_RES_GW(*res); |
802 | memcpy(rt->dst.metrics, fi->fib_metrics, | 824 | dst_import_metrics(&rt->dst, fi->fib_metrics); |
803 | sizeof(rt->dst.metrics)); | ||
804 | } | 825 | } |
805 | rt->rt_type = res->type; | 826 | rt->rt_type = res->type; |
806 | 827 | ||
@@ -811,13 +832,14 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | |||
811 | rt->dst.neighbour = n; | 832 | rt->dst.neighbour = n; |
812 | } | 833 | } |
813 | 834 | ||
814 | if (dst_metric(&rt->dst, RTAX_MTU) == 0 || | 835 | if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) |
815 | dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) | 836 | dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu); |
816 | rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; | 837 | metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS); |
817 | mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); | 838 | if (metric) { |
818 | if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 || | 839 | unsigned int mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); |
819 | dst_metric(&rt->dst, RTAX_ADVMSS) > mss) | 840 | if (metric > mss) |
820 | rt->dst.metrics[RTAX_ADVMSS-1] = mss; | 841 | dst_metric_set(&rt->dst, RTAX_ADVMSS, mss); |
842 | } | ||
821 | return 0; | 843 | return 0; |
822 | } | 844 | } |
823 | 845 | ||
@@ -835,13 +857,16 @@ static inline int dn_match_addr(__le16 addr1, __le16 addr2) | |||
835 | static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope) | 857 | static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope) |
836 | { | 858 | { |
837 | __le16 saddr = 0; | 859 | __le16 saddr = 0; |
838 | struct dn_dev *dn_db = dev->dn_ptr; | 860 | struct dn_dev *dn_db; |
839 | struct dn_ifaddr *ifa; | 861 | struct dn_ifaddr *ifa; |
840 | int best_match = 0; | 862 | int best_match = 0; |
841 | int ret; | 863 | int ret; |
842 | 864 | ||
843 | read_lock(&dev_base_lock); | 865 | rcu_read_lock(); |
844 | for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) { | 866 | dn_db = rcu_dereference(dev->dn_ptr); |
867 | for (ifa = rcu_dereference(dn_db->ifa_list); | ||
868 | ifa != NULL; | ||
869 | ifa = rcu_dereference(ifa->ifa_next)) { | ||
845 | if (ifa->ifa_scope > scope) | 870 | if (ifa->ifa_scope > scope) |
846 | continue; | 871 | continue; |
847 | if (!daddr) { | 872 | if (!daddr) { |
@@ -854,7 +879,7 @@ static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int | |||
854 | if (best_match == 0) | 879 | if (best_match == 0) |
855 | saddr = ifa->ifa_local; | 880 | saddr = ifa->ifa_local; |
856 | } | 881 | } |
857 | read_unlock(&dev_base_lock); | 882 | rcu_read_unlock(); |
858 | 883 | ||
859 | return saddr; | 884 | return saddr; |
860 | } | 885 | } |
@@ -872,11 +897,9 @@ static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_re | |||
872 | 897 | ||
873 | static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard) | 898 | static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard) |
874 | { | 899 | { |
875 | struct flowi fl = { .nl_u = { .dn_u = | 900 | struct flowi fl = { .fld_dst = oldflp->fld_dst, |
876 | { .daddr = oldflp->fld_dst, | 901 | .fld_src = oldflp->fld_src, |
877 | .saddr = oldflp->fld_src, | 902 | .fld_scope = RT_SCOPE_UNIVERSE, |
878 | .scope = RT_SCOPE_UNIVERSE, | ||
879 | } }, | ||
880 | .mark = oldflp->mark, | 903 | .mark = oldflp->mark, |
881 | .iif = init_net.loopback_dev->ifindex, | 904 | .iif = init_net.loopback_dev->ifindex, |
882 | .oif = oldflp->oif }; | 905 | .oif = oldflp->oif }; |
@@ -1020,7 +1043,7 @@ source_ok: | |||
1020 | err = -ENODEV; | 1043 | err = -ENODEV; |
1021 | if (dev_out == NULL) | 1044 | if (dev_out == NULL) |
1022 | goto out; | 1045 | goto out; |
1023 | dn_db = dev_out->dn_ptr; | 1046 | dn_db = rcu_dereference_raw(dev_out->dn_ptr); |
1024 | /* Possible improvement - check all devices for local addr */ | 1047 | /* Possible improvement - check all devices for local addr */ |
1025 | if (dn_dev_islocal(dev_out, fl.fld_dst)) { | 1048 | if (dn_dev_islocal(dev_out, fl.fld_dst)) { |
1026 | dev_put(dev_out); | 1049 | dev_put(dev_out); |
@@ -1171,7 +1194,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl | |||
1171 | if ((flp->fld_dst == rt->fl.fld_dst) && | 1194 | if ((flp->fld_dst == rt->fl.fld_dst) && |
1172 | (flp->fld_src == rt->fl.fld_src) && | 1195 | (flp->fld_src == rt->fl.fld_src) && |
1173 | (flp->mark == rt->fl.mark) && | 1196 | (flp->mark == rt->fl.mark) && |
1174 | (rt->fl.iif == 0) && | 1197 | dn_is_output_route(rt) && |
1175 | (rt->fl.oif == flp->oif)) { | 1198 | (rt->fl.oif == flp->oif)) { |
1176 | dst_use(&rt->dst, jiffies); | 1199 | dst_use(&rt->dst, jiffies); |
1177 | rcu_read_unlock_bh(); | 1200 | rcu_read_unlock_bh(); |
@@ -1220,11 +1243,9 @@ static int dn_route_input_slow(struct sk_buff *skb) | |||
1220 | int flags = 0; | 1243 | int flags = 0; |
1221 | __le16 gateway = 0; | 1244 | __le16 gateway = 0; |
1222 | __le16 local_src = 0; | 1245 | __le16 local_src = 0; |
1223 | struct flowi fl = { .nl_u = { .dn_u = | 1246 | struct flowi fl = { .fld_dst = cb->dst, |
1224 | { .daddr = cb->dst, | 1247 | .fld_src = cb->src, |
1225 | .saddr = cb->src, | 1248 | .fld_scope = RT_SCOPE_UNIVERSE, |
1226 | .scope = RT_SCOPE_UNIVERSE, | ||
1227 | } }, | ||
1228 | .mark = skb->mark, | 1249 | .mark = skb->mark, |
1229 | .iif = skb->dev->ifindex }; | 1250 | .iif = skb->dev->ifindex }; |
1230 | struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; | 1251 | struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; |
@@ -1233,7 +1254,7 @@ static int dn_route_input_slow(struct sk_buff *skb) | |||
1233 | 1254 | ||
1234 | dev_hold(in_dev); | 1255 | dev_hold(in_dev); |
1235 | 1256 | ||
1236 | if ((dn_db = in_dev->dn_ptr) == NULL) | 1257 | if ((dn_db = rcu_dereference(in_dev->dn_ptr)) == NULL) |
1237 | goto out; | 1258 | goto out; |
1238 | 1259 | ||
1239 | /* Zero source addresses are not allowed */ | 1260 | /* Zero source addresses are not allowed */ |
@@ -1496,13 +1517,13 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | |||
1496 | RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); | 1517 | RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); |
1497 | if (rt->rt_daddr != rt->rt_gateway) | 1518 | if (rt->rt_daddr != rt->rt_gateway) |
1498 | RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); | 1519 | RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); |
1499 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) | 1520 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
1500 | goto rtattr_failure; | 1521 | goto rtattr_failure; |
1501 | expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; | 1522 | expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; |
1502 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, | 1523 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, |
1503 | rt->dst.error) < 0) | 1524 | rt->dst.error) < 0) |
1504 | goto rtattr_failure; | 1525 | goto rtattr_failure; |
1505 | if (rt->fl.iif) | 1526 | if (dn_is_input_route(rt)) |
1506 | RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); | 1527 | RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); |
1507 | 1528 | ||
1508 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 1529 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
@@ -1677,15 +1698,15 @@ static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_rou | |||
1677 | { | 1698 | { |
1678 | struct dn_rt_cache_iter_state *s = seq->private; | 1699 | struct dn_rt_cache_iter_state *s = seq->private; |
1679 | 1700 | ||
1680 | rt = rt->dst.dn_next; | 1701 | rt = rcu_dereference_bh(rt->dst.dn_next); |
1681 | while(!rt) { | 1702 | while (!rt) { |
1682 | rcu_read_unlock_bh(); | 1703 | rcu_read_unlock_bh(); |
1683 | if (--s->bucket < 0) | 1704 | if (--s->bucket < 0) |
1684 | break; | 1705 | break; |
1685 | rcu_read_lock_bh(); | 1706 | rcu_read_lock_bh(); |
1686 | rt = dn_rt_hash_table[s->bucket].chain; | 1707 | rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain); |
1687 | } | 1708 | } |
1688 | return rcu_dereference_bh(rt); | 1709 | return rt; |
1689 | } | 1710 | } |
1690 | 1711 | ||
1691 | static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos) | 1712 | static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos) |
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 48fdf10be7a1..6eb91df3c550 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
@@ -175,7 +175,7 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
175 | 175 | ||
176 | unsigned dnet_addr_type(__le16 addr) | 176 | unsigned dnet_addr_type(__le16 addr) |
177 | { | 177 | { |
178 | struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; | 178 | struct flowi fl = { .fld_dst = addr }; |
179 | struct dn_fib_res res; | 179 | struct dn_fib_res res; |
180 | unsigned ret = RTN_UNICAST; | 180 | unsigned ret = RTN_UNICAST; |
181 | struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0); | 181 | struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0); |