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

mld: convert ifmcaddr6 to RCU

The ifmcaddr6 has been protected by inet6_dev->lock(rwlock) so that
the critical section is atomic context. In order to switch this context,
changing locking is needed. The ifmcaddr6 actually already protected by
RTNL So if it's converted to use RCU, its control path context can be
switched to sleepable.

Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Taehee Yoo and committed by
David S. Miller
88e2ca30 4b200e39

+140 -188
+3 -3
drivers/s390/net/qeth_l3_main.c
··· 1098 1098 tmp.disp_flag = QETH_DISP_ADDR_ADD; 1099 1099 tmp.is_multicast = 1; 1100 1100 1101 - read_lock_bh(&in6_dev->lock); 1102 - for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) { 1101 + for (im6 = rtnl_dereference(in6_dev->mc_list); 1102 + im6; 1103 + im6 = rtnl_dereference(im6->next)) { 1103 1104 tmp.u.a6.addr = im6->mca_addr; 1104 1105 1105 1106 ipm = qeth_l3_find_addr_by_ip(card, &tmp); ··· 1118 1117 qeth_l3_ipaddr_hash(ipm)); 1119 1118 1120 1119 } 1121 - read_unlock_bh(&in6_dev->lock); 1122 1120 1123 1121 out: 1124 1122 return 0;
+4 -3
include/net/if_inet6.h
··· 115 115 struct ifmcaddr6 { 116 116 struct in6_addr mca_addr; 117 117 struct inet6_dev *idev; 118 - struct ifmcaddr6 *next; 118 + struct ifmcaddr6 __rcu *next; 119 119 struct ip6_sf_list __rcu *mca_sources; 120 120 struct ip6_sf_list __rcu *mca_tomb; 121 121 unsigned int mca_sfmode; ··· 128 128 spinlock_t mca_lock; 129 129 unsigned long mca_cstamp; 130 130 unsigned long mca_tstamp; 131 + struct rcu_head rcu; 131 132 }; 132 133 133 134 /* Anycast stuff */ ··· 167 166 168 167 struct list_head addr_list; 169 168 170 - struct ifmcaddr6 *mc_list; 171 - struct ifmcaddr6 *mc_tomb; 169 + struct ifmcaddr6 __rcu *mc_list; 170 + struct ifmcaddr6 __rcu *mc_tomb; 172 171 173 172 unsigned char mc_qrv; /* Query Robustness Variable */ 174 173 unsigned char mc_gq_running;
+3 -3
net/batman-adv/multicast.c
··· 454 454 return 0; 455 455 } 456 456 457 - read_lock_bh(&in6_dev->lock); 458 - for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) { 457 + for (pmc6 = rcu_dereference(in6_dev->mc_list); 458 + pmc6; 459 + pmc6 = rcu_dereference(pmc6->next)) { 459 460 if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) < 460 461 IPV6_ADDR_SCOPE_LINKLOCAL) 461 462 continue; ··· 485 484 hlist_add_head(&new->list, mcast_list); 486 485 ret++; 487 486 } 488 - read_unlock_bh(&in6_dev->lock); 489 487 rcu_read_unlock(); 490 488 491 489 return ret;
+5 -4
net/ipv6/addrconf.c
··· 5107 5107 break; 5108 5108 } 5109 5109 case MULTICAST_ADDR: 5110 + read_unlock_bh(&idev->lock); 5110 5111 fillargs->event = RTM_GETMULTICAST; 5111 5112 5112 5113 /* multicast address */ 5113 - for (ifmca = idev->mc_list; ifmca; 5114 - ifmca = ifmca->next, ip_idx++) { 5114 + for (ifmca = rcu_dereference(idev->mc_list); 5115 + ifmca; 5116 + ifmca = rcu_dereference(ifmca->next), ip_idx++) { 5115 5117 if (ip_idx < s_ip_idx) 5116 5118 continue; 5117 5119 err = inet6_fill_ifmcaddr(skb, ifmca, fillargs); 5118 5120 if (err < 0) 5119 5121 break; 5120 5122 } 5123 + read_lock_bh(&idev->lock); 5121 5124 break; 5122 5125 case ANYCAST_ADDR: 5123 5126 fillargs->event = RTM_GETANYCAST; ··· 6096 6093 6097 6094 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 6098 6095 { 6099 - rcu_read_lock_bh(); 6100 6096 if (likely(ifp->idev->dead == 0)) 6101 6097 __ipv6_ifa_notify(event, ifp); 6102 - rcu_read_unlock_bh(); 6103 6098 } 6104 6099 6105 6100 #ifdef CONFIG_SYSCTL
+1 -1
net/ipv6/addrconf_core.c
··· 250 250 struct net_device *dev = idev->dev; 251 251 252 252 WARN_ON(!list_empty(&idev->addr_list)); 253 - WARN_ON(idev->mc_list); 253 + WARN_ON(rcu_access_pointer(idev->mc_list)); 254 254 WARN_ON(timer_pending(&idev->rs_timer)); 255 255 256 256 #ifdef NET_REFCNT_DEBUG
+1 -1
net/ipv6/af_inet6.c
··· 222 222 inet->mc_loop = 1; 223 223 inet->mc_ttl = 1; 224 224 inet->mc_index = 0; 225 - inet->mc_list = NULL; 225 + RCU_INIT_POINTER(inet->mc_list, NULL); 226 226 inet->rcv_tos = 0; 227 227 228 228 if (net->ipv4.sysctl_ip_no_pmtu_disc)
+123 -173
net/ipv6/mcast.c
··· 112 112 * socket join on multicast group 113 113 */ 114 114 115 + #define for_each_pmc_rtnl(np, pmc) \ 116 + for (pmc = rtnl_dereference((np)->ipv6_mc_list); \ 117 + pmc; \ 118 + pmc = rtnl_dereference(pmc->next)) 119 + 115 120 #define for_each_pmc_rcu(np, pmc) \ 116 121 for (pmc = rcu_dereference((np)->ipv6_mc_list); \ 117 122 pmc; \ ··· 136 131 for (psf = rtnl_dereference((mc)->mca_tomb); \ 137 132 psf; \ 138 133 psf = rtnl_dereference(psf->sf_next)) 134 + 135 + #define for_each_mc_rtnl(idev, mc) \ 136 + for (mc = rtnl_dereference((idev)->mc_list); \ 137 + mc; \ 138 + mc = rtnl_dereference(mc->next)) 139 + 140 + #define for_each_mc_rcu(idev, mc) \ 141 + for (mc = rcu_dereference((idev)->mc_list); \ 142 + mc; \ 143 + mc = rcu_dereference(mc->next)) 144 + 145 + #define for_each_mc_tomb(idev, mc) \ 146 + for (mc = rtnl_dereference((idev)->mc_tomb); \ 147 + mc; \ 148 + mc = rtnl_dereference(mc->next)) 139 149 140 150 static int unsolicited_report_interval(struct inet6_dev *idev) 141 151 { ··· 178 158 if (!ipv6_addr_is_multicast(addr)) 179 159 return -EINVAL; 180 160 181 - rcu_read_lock(); 182 - for_each_pmc_rcu(np, mc_lst) { 161 + for_each_pmc_rtnl(np, mc_lst) { 183 162 if ((ifindex == 0 || mc_lst->ifindex == ifindex) && 184 - ipv6_addr_equal(&mc_lst->addr, addr)) { 185 - rcu_read_unlock(); 163 + ipv6_addr_equal(&mc_lst->addr, addr)) 186 164 return -EADDRINUSE; 187 - } 188 165 } 189 - rcu_read_unlock(); 190 166 191 167 mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL); 192 168 ··· 284 268 } 285 269 EXPORT_SYMBOL(ipv6_sock_mc_drop); 286 270 287 - /* called with rcu_read_lock() */ 288 - static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, 289 - const struct in6_addr *group, 290 - int ifindex) 271 + static struct inet6_dev *ip6_mc_find_dev_rtnl(struct net *net, 272 + const struct in6_addr *group, 273 + int ifindex) 291 274 { 292 275 struct net_device *dev = NULL; 293 276 struct inet6_dev *idev = NULL; ··· 298 283 dev = rt->dst.dev; 299 284 ip6_rt_put(rt); 300 285 } 301 - } else 302 - dev = dev_get_by_index_rcu(net, ifindex); 286 + } else { 287 + dev = __dev_get_by_index(net, ifindex); 288 + } 303 289 304 290 if (!dev) 305 291 return NULL; 306 292 idev = __in6_dev_get(dev); 307 293 if (!idev) 308 294 return NULL; 309 - read_lock_bh(&idev->lock); 310 - if (idev->dead) { 311 - read_unlock_bh(&idev->lock); 295 + if (idev->dead) 312 296 return NULL; 313 - } 314 297 return idev; 315 298 } 316 299 ··· 370 357 if (!ipv6_addr_is_multicast(group)) 371 358 return -EINVAL; 372 359 373 - rcu_read_lock(); 374 - idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface); 375 - if (!idev) { 376 - rcu_read_unlock(); 360 + idev = ip6_mc_find_dev_rtnl(net, group, pgsr->gsr_interface); 361 + if (!idev) 377 362 return -ENODEV; 378 - } 379 363 380 364 err = -EADDRNOTAVAIL; 381 365 382 - for_each_pmc_rcu(inet6, pmc) { 366 + for_each_pmc_rtnl(inet6, pmc) { 383 367 if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) 384 368 continue; 385 369 if (ipv6_addr_equal(&pmc->addr, group)) ··· 469 459 /* update the interface list */ 470 460 ip6_mc_add_src(idev, group, omode, 1, source, 1); 471 461 done: 472 - read_unlock_bh(&idev->lock); 473 - rcu_read_unlock(); 474 462 if (leavegroup) 475 463 err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); 476 464 return err; ··· 494 486 gsf->gf_fmode != MCAST_EXCLUDE) 495 487 return -EINVAL; 496 488 497 - rcu_read_lock(); 498 - idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); 499 - 500 - if (!idev) { 501 - rcu_read_unlock(); 489 + idev = ip6_mc_find_dev_rtnl(net, group, gsf->gf_interface); 490 + if (!idev) 502 491 return -ENODEV; 503 - } 504 492 505 493 err = 0; 506 494 ··· 505 501 goto done; 506 502 } 507 503 508 - for_each_pmc_rcu(inet6, pmc) { 504 + for_each_pmc_rtnl(inet6, pmc) { 509 505 if (pmc->ifindex != gsf->gf_interface) 510 506 continue; 511 507 if (ipv6_addr_equal(&pmc->addr, group)) ··· 552 548 pmc->sfmode = gsf->gf_fmode; 553 549 err = 0; 554 550 done: 555 - read_unlock_bh(&idev->lock); 556 - rcu_read_unlock(); 557 551 if (leavegroup) 558 552 err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); 559 553 return err; ··· 573 571 if (!ipv6_addr_is_multicast(group)) 574 572 return -EINVAL; 575 573 576 - rcu_read_lock(); 577 - idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); 578 - 579 - if (!idev) { 580 - rcu_read_unlock(); 574 + idev = ip6_mc_find_dev_rtnl(net, group, gsf->gf_interface); 575 + if (!idev) 581 576 return -ENODEV; 582 - } 583 577 584 578 err = -EADDRNOTAVAIL; 585 579 /* changes to the ipv6_mc_list require the socket lock and ··· 583 585 * so reading the list is safe. 584 586 */ 585 587 586 - for_each_pmc_rcu(inet6, pmc) { 588 + for_each_pmc_rtnl(inet6, pmc) { 587 589 if (pmc->ifindex != gsf->gf_interface) 588 590 continue; 589 591 if (ipv6_addr_equal(group, &pmc->addr)) 590 592 break; 591 593 } 592 594 if (!pmc) /* must have a prior join */ 593 - goto done; 595 + return err; 596 + 594 597 gsf->gf_fmode = pmc->sfmode; 595 598 psl = rtnl_dereference(pmc->sflist); 596 599 count = psl ? psl->sl_count : 0; 597 - read_unlock_bh(&idev->lock); 598 - rcu_read_unlock(); 599 600 600 601 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; 601 602 gsf->gf_numsrc = count; ··· 611 614 return -EFAULT; 612 615 } 613 616 return 0; 614 - done: 615 - read_unlock_bh(&idev->lock); 616 - rcu_read_unlock(); 617 - return err; 618 617 } 619 618 620 619 bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, ··· 754 761 } 755 762 spin_unlock_bh(&im->mca_lock); 756 763 757 - pmc->next = idev->mc_tomb; 758 - idev->mc_tomb = pmc; 764 + rcu_assign_pointer(pmc->next, idev->mc_tomb); 765 + rcu_assign_pointer(idev->mc_tomb, pmc); 759 766 } 760 767 761 768 static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) ··· 765 772 struct ifmcaddr6 *pmc, *pmc_prev; 766 773 767 774 pmc_prev = NULL; 768 - for (pmc = idev->mc_tomb; pmc; pmc = pmc->next) { 775 + for_each_mc_tomb(idev, pmc) { 769 776 if (ipv6_addr_equal(&pmc->mca_addr, pmca)) 770 777 break; 771 778 pmc_prev = pmc; 772 779 } 773 780 if (pmc) { 774 781 if (pmc_prev) 775 - pmc_prev->next = pmc->next; 782 + rcu_assign_pointer(pmc_prev->next, pmc->next); 776 783 else 777 - idev->mc_tomb = pmc->next; 784 + rcu_assign_pointer(idev->mc_tomb, pmc->next); 778 785 } 779 786 780 787 spin_lock_bh(&im->mca_lock); ··· 797 804 } 798 805 in6_dev_put(pmc->idev); 799 806 ip6_mc_clear_src(pmc); 800 - kfree(pmc); 807 + kfree_rcu(pmc, rcu); 801 808 } 802 809 spin_unlock_bh(&im->mca_lock); 803 810 } ··· 806 813 { 807 814 struct ifmcaddr6 *pmc, *nextpmc; 808 815 809 - pmc = idev->mc_tomb; 810 - idev->mc_tomb = NULL; 816 + pmc = rtnl_dereference(idev->mc_tomb); 817 + RCU_INIT_POINTER(idev->mc_tomb, NULL); 811 818 812 819 for (; pmc; pmc = nextpmc) { 813 - nextpmc = pmc->next; 820 + nextpmc = rtnl_dereference(pmc->next); 814 821 ip6_mc_clear_src(pmc); 815 822 in6_dev_put(pmc->idev); 816 - kfree(pmc); 823 + kfree_rcu(pmc, rcu); 817 824 } 818 825 819 826 /* clear dead sources, too */ 820 - read_lock_bh(&idev->lock); 821 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 827 + for_each_mc_rtnl(idev, pmc) { 822 828 struct ip6_sf_list *psf, *psf_next; 823 829 824 830 spin_lock_bh(&pmc->mca_lock); ··· 829 837 kfree_rcu(psf, rcu); 830 838 } 831 839 } 832 - read_unlock_bh(&idev->lock); 833 840 } 834 841 835 842 static void mca_get(struct ifmcaddr6 *mc) ··· 840 849 { 841 850 if (refcount_dec_and_test(&mc->mca_refcnt)) { 842 851 in6_dev_put(mc->idev); 843 - kfree(mc); 852 + kfree_rcu(mc, rcu); 844 853 } 845 854 } 846 855 ··· 891 900 if (!idev) 892 901 return -EINVAL; 893 902 894 - write_lock_bh(&idev->lock); 895 903 if (idev->dead) { 896 - write_unlock_bh(&idev->lock); 897 904 in6_dev_put(idev); 898 905 return -ENODEV; 899 906 } 900 907 901 - for (mc = idev->mc_list; mc; mc = mc->next) { 908 + for_each_mc_rtnl(idev, mc) { 902 909 if (ipv6_addr_equal(&mc->mca_addr, addr)) { 903 910 mc->mca_users++; 904 - write_unlock_bh(&idev->lock); 905 911 ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0); 906 912 in6_dev_put(idev); 907 913 return 0; ··· 907 919 908 920 mc = mca_alloc(idev, addr, mode); 909 921 if (!mc) { 910 - write_unlock_bh(&idev->lock); 911 922 in6_dev_put(idev); 912 923 return -ENOMEM; 913 924 } 914 925 915 - mc->next = idev->mc_list; 916 - idev->mc_list = mc; 926 + rcu_assign_pointer(mc->next, idev->mc_list); 927 + rcu_assign_pointer(idev->mc_list, mc); 917 928 918 - /* Hold this for the code below before we unlock, 919 - * it is already exposed via idev->mc_list. 920 - */ 921 929 mca_get(mc); 922 - write_unlock_bh(&idev->lock); 923 930 924 931 mld_del_delrec(idev, mc); 925 932 igmp6_group_added(mc); ··· 933 950 */ 934 951 int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) 935 952 { 936 - struct ifmcaddr6 *ma, **map; 953 + struct ifmcaddr6 *ma, __rcu **map; 937 954 938 955 ASSERT_RTNL(); 939 956 940 - write_lock_bh(&idev->lock); 941 - for (map = &idev->mc_list; (ma = *map) != NULL; map = &ma->next) { 957 + for (map = &idev->mc_list; 958 + (ma = rtnl_dereference(*map)); 959 + map = &ma->next) { 942 960 if (ipv6_addr_equal(&ma->mca_addr, addr)) { 943 961 if (--ma->mca_users == 0) { 944 962 *map = ma->next; 945 - write_unlock_bh(&idev->lock); 946 963 947 964 igmp6_group_dropped(ma); 948 965 ip6_mc_clear_src(ma); ··· 950 967 ma_put(ma); 951 968 return 0; 952 969 } 953 - write_unlock_bh(&idev->lock); 954 970 return 0; 955 971 } 956 972 } 957 - write_unlock_bh(&idev->lock); 958 973 959 974 return -ENOENT; 960 975 } ··· 987 1006 rcu_read_lock(); 988 1007 idev = __in6_dev_get(dev); 989 1008 if (idev) { 990 - read_lock_bh(&idev->lock); 991 - for (mc = idev->mc_list; mc; mc = mc->next) { 1009 + for_each_mc_rcu(idev, mc) { 992 1010 if (ipv6_addr_equal(&mc->mca_addr, group)) 993 1011 break; 994 1012 } ··· 1010 1030 } else 1011 1031 rv = true; /* don't filter unspecified source */ 1012 1032 } 1013 - read_unlock_bh(&idev->lock); 1014 1033 } 1015 1034 rcu_read_unlock(); 1016 1035 return rv; ··· 1061 1082 } 1062 1083 1063 1084 /* 1064 - * IGMP handling (alias multicast ICMPv6 messages) 1085 + * IGMP handling (alias multicast ICMPv6 messages) 1065 1086 */ 1066 - 1067 1087 static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime) 1068 1088 { 1069 1089 unsigned long delay = resptime; ··· 1400 1422 return -EINVAL; 1401 1423 } 1402 1424 1403 - read_lock_bh(&idev->lock); 1404 1425 if (group_type == IPV6_ADDR_ANY) { 1405 - for (ma = idev->mc_list; ma; ma = ma->next) { 1426 + for_each_mc_rcu(idev, ma) { 1406 1427 spin_lock_bh(&ma->mca_lock); 1407 1428 igmp6_group_queried(ma, max_delay); 1408 1429 spin_unlock_bh(&ma->mca_lock); 1409 1430 } 1410 1431 } else { 1411 - for (ma = idev->mc_list; ma; ma = ma->next) { 1432 + for_each_mc_rcu(idev, ma) { 1412 1433 if (!ipv6_addr_equal(group, &ma->mca_addr)) 1413 1434 continue; 1414 1435 spin_lock_bh(&ma->mca_lock); ··· 1429 1452 break; 1430 1453 } 1431 1454 } 1432 - read_unlock_bh(&idev->lock); 1433 1455 1434 1456 return 0; 1435 1457 } ··· 1469 1493 * Cancel the work for this group 1470 1494 */ 1471 1495 1472 - read_lock_bh(&idev->lock); 1473 - for (ma = idev->mc_list; ma; ma = ma->next) { 1496 + for_each_mc_rcu(idev, ma) { 1474 1497 if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { 1475 1498 spin_lock(&ma->mca_lock); 1476 1499 if (cancel_delayed_work(&ma->mca_work)) 1477 1500 refcount_dec(&ma->mca_refcnt); 1478 - ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING); 1501 + ma->mca_flags &= ~(MAF_LAST_REPORTER | 1502 + MAF_TIMER_RUNNING); 1479 1503 spin_unlock(&ma->mca_lock); 1480 1504 break; 1481 1505 } 1482 1506 } 1483 - read_unlock_bh(&idev->lock); 1484 1507 return 0; 1485 1508 } 1486 1509 ··· 1843 1868 struct sk_buff *skb = NULL; 1844 1869 int type; 1845 1870 1846 - read_lock_bh(&idev->lock); 1847 1871 if (!pmc) { 1848 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 1872 + for_each_mc_rtnl(idev, pmc) { 1849 1873 if (pmc->mca_flags & MAF_NOREPORT) 1850 1874 continue; 1851 1875 spin_lock_bh(&pmc->mca_lock); ··· 1864 1890 skb = add_grec(skb, pmc, type, 0, 0, 0); 1865 1891 spin_unlock_bh(&pmc->mca_lock); 1866 1892 } 1867 - read_unlock_bh(&idev->lock); 1868 1893 if (skb) 1869 1894 mld_sendpack(skb); 1870 1895 } ··· 1900 1927 struct sk_buff *skb = NULL; 1901 1928 int type, dtype; 1902 1929 1903 - read_lock_bh(&idev->lock); 1904 - 1905 1930 /* deleted MCA's */ 1906 1931 pmc_prev = NULL; 1907 - for (pmc = idev->mc_tomb; pmc; pmc = pmc_next) { 1908 - pmc_next = pmc->next; 1932 + for (pmc = rtnl_dereference(idev->mc_tomb); 1933 + pmc; 1934 + pmc = pmc_next) { 1935 + pmc_next = rtnl_dereference(pmc->next); 1909 1936 if (pmc->mca_sfmode == MCAST_INCLUDE) { 1910 1937 type = MLD2_BLOCK_OLD_SOURCES; 1911 1938 dtype = MLD2_BLOCK_OLD_SOURCES; ··· 1927 1954 !rcu_access_pointer(pmc->mca_tomb) && 1928 1955 !rcu_access_pointer(pmc->mca_sources)) { 1929 1956 if (pmc_prev) 1930 - pmc_prev->next = pmc_next; 1957 + rcu_assign_pointer(pmc_prev->next, pmc_next); 1931 1958 else 1932 - idev->mc_tomb = pmc_next; 1959 + rcu_assign_pointer(idev->mc_tomb, pmc_next); 1933 1960 in6_dev_put(pmc->idev); 1934 - kfree(pmc); 1961 + kfree_rcu(pmc, rcu); 1935 1962 } else 1936 1963 pmc_prev = pmc; 1937 1964 } 1938 1965 1939 1966 /* change recs */ 1940 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 1967 + for_each_mc_rtnl(idev, pmc) { 1941 1968 spin_lock_bh(&pmc->mca_lock); 1942 1969 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { 1943 1970 type = MLD2_BLOCK_OLD_SOURCES; ··· 1960 1987 } 1961 1988 spin_unlock_bh(&pmc->mca_lock); 1962 1989 } 1963 - read_unlock_bh(&idev->lock); 1964 1990 if (!skb) 1965 1991 return; 1966 1992 (void) mld_sendpack(skb); ··· 2071 2099 return; 2072 2100 2073 2101 skb = NULL; 2074 - read_lock_bh(&idev->lock); 2075 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 2102 + for_each_mc_rtnl(idev, pmc) { 2076 2103 spin_lock_bh(&pmc->mca_lock); 2077 2104 if (pmc->mca_sfcount[MCAST_EXCLUDE]) 2078 2105 type = MLD2_CHANGE_TO_EXCLUDE; ··· 2080 2109 skb = add_grec(skb, pmc, type, 0, 0, 1); 2081 2110 spin_unlock_bh(&pmc->mca_lock); 2082 2111 } 2083 - read_unlock_bh(&idev->lock); 2084 2112 if (skb) 2085 2113 mld_sendpack(skb); 2086 2114 } ··· 2102 2132 struct inet6_dev, 2103 2133 mc_dad_work); 2104 2134 2135 + rtnl_lock(); 2105 2136 mld_send_initial_cr(idev); 2137 + rtnl_unlock(); 2106 2138 if (idev->mc_dad_count) { 2107 2139 idev->mc_dad_count--; 2108 2140 if (idev->mc_dad_count) ··· 2166 2194 2167 2195 if (!idev) 2168 2196 return -ENODEV; 2169 - read_lock_bh(&idev->lock); 2170 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 2197 + 2198 + for_each_mc_rtnl(idev, pmc) { 2171 2199 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) 2172 2200 break; 2173 2201 } 2174 - if (!pmc) { 2175 - /* MCA not found?? bug */ 2176 - read_unlock_bh(&idev->lock); 2202 + if (!pmc) 2177 2203 return -ESRCH; 2178 - } 2179 2204 spin_lock_bh(&pmc->mca_lock); 2205 + 2180 2206 sf_markstate(pmc); 2181 2207 if (!delta) { 2182 2208 if (!pmc->mca_sfcount[sfmode]) { 2183 2209 spin_unlock_bh(&pmc->mca_lock); 2184 - read_unlock_bh(&idev->lock); 2185 2210 return -EINVAL; 2186 2211 } 2212 + 2187 2213 pmc->mca_sfcount[sfmode]--; 2188 2214 } 2189 2215 err = 0; ··· 2207 2237 } else if (sf_setstate(pmc) || changerec) 2208 2238 mld_ifc_event(pmc->idev); 2209 2239 spin_unlock_bh(&pmc->mca_lock); 2210 - read_unlock_bh(&idev->lock); 2211 2240 return err; 2212 2241 } 2213 2242 ··· 2332 2363 2333 2364 if (!idev) 2334 2365 return -ENODEV; 2335 - read_lock_bh(&idev->lock); 2336 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) { 2366 + 2367 + for_each_mc_rtnl(idev, pmc) { 2337 2368 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) 2338 2369 break; 2339 2370 } 2340 - if (!pmc) { 2341 - /* MCA not found?? bug */ 2342 - read_unlock_bh(&idev->lock); 2371 + if (!pmc) 2343 2372 return -ESRCH; 2344 - } 2345 2373 spin_lock_bh(&pmc->mca_lock); 2346 2374 2347 2375 sf_markstate(pmc); ··· 2373 2407 for_each_psf_rtnl(pmc, psf) 2374 2408 psf->sf_crcount = 0; 2375 2409 mld_ifc_event(idev); 2376 - } else if (sf_setstate(pmc)) 2410 + } else if (sf_setstate(pmc)) { 2377 2411 mld_ifc_event(idev); 2412 + } 2378 2413 spin_unlock_bh(&pmc->mca_lock); 2379 - read_unlock_bh(&idev->lock); 2380 2414 return err; 2381 2415 } 2382 2416 ··· 2451 2485 static void igmp6_leave_group(struct ifmcaddr6 *ma) 2452 2486 { 2453 2487 if (mld_in_v1_mode(ma->idev)) { 2454 - if (ma->mca_flags & MAF_LAST_REPORTER) 2488 + if (ma->mca_flags & MAF_LAST_REPORTER) { 2455 2489 igmp6_send(&ma->mca_addr, ma->idev->dev, 2456 2490 ICMPV6_MGM_REDUCTION); 2491 + } 2457 2492 } else { 2458 2493 mld_add_delrec(ma->idev, ma); 2459 2494 mld_ifc_event(ma->idev); ··· 2467 2500 struct inet6_dev, 2468 2501 mc_gq_work); 2469 2502 2470 - idev->mc_gq_running = 0; 2503 + rtnl_lock(); 2471 2504 mld_send_report(idev, NULL); 2505 + rtnl_unlock(); 2506 + 2507 + idev->mc_gq_running = 0; 2508 + 2472 2509 in6_dev_put(idev); 2473 2510 } 2474 2511 ··· 2482 2511 struct inet6_dev, 2483 2512 mc_ifc_work); 2484 2513 2514 + rtnl_lock(); 2485 2515 mld_send_cr(idev); 2516 + rtnl_unlock(); 2517 + 2486 2518 if (idev->mc_ifc_count) { 2487 2519 idev->mc_ifc_count--; 2488 2520 if (idev->mc_ifc_count) ··· 2499 2525 { 2500 2526 if (mld_in_v1_mode(idev)) 2501 2527 return; 2528 + 2502 2529 idev->mc_ifc_count = idev->mc_qrv; 2503 2530 mld_ifc_start_work(idev, 1); 2504 2531 } ··· 2509 2534 struct ifmcaddr6 *ma = container_of(to_delayed_work(work), 2510 2535 struct ifmcaddr6, mca_work); 2511 2536 2537 + rtnl_lock(); 2512 2538 if (mld_in_v1_mode(ma->idev)) 2513 2539 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); 2514 2540 else 2515 2541 mld_send_report(ma->idev, ma); 2542 + rtnl_unlock(); 2516 2543 2517 2544 spin_lock_bh(&ma->mca_lock); 2518 2545 ma->mca_flags |= MAF_LAST_REPORTER; ··· 2531 2554 2532 2555 /* Install multicast list, except for all-nodes (already installed) */ 2533 2556 2534 - read_lock_bh(&idev->lock); 2535 - for (i = idev->mc_list; i; i = i->next) 2557 + for_each_mc_rtnl(idev, i) 2536 2558 igmp6_group_dropped(i); 2537 - read_unlock_bh(&idev->lock); 2538 2559 } 2539 2560 2540 2561 void ipv6_mc_remap(struct inet6_dev *idev) ··· 2547 2572 struct ifmcaddr6 *i; 2548 2573 2549 2574 /* Withdraw multicast list */ 2550 - 2551 - read_lock_bh(&idev->lock); 2552 - 2553 - for (i = idev->mc_list; i; i = i->next) 2575 + for_each_mc_rtnl(idev, i) 2554 2576 igmp6_group_dropped(i); 2555 2577 2556 2578 /* Should stop work after group drop. or we will ··· 2556 2584 mld_ifc_stop_work(idev); 2557 2585 mld_gq_stop_work(idev); 2558 2586 mld_dad_stop_work(idev); 2559 - read_unlock_bh(&idev->lock); 2560 2587 } 2561 2588 2562 2589 static void ipv6_mc_reset(struct inet6_dev *idev) ··· 2575 2604 2576 2605 /* Install multicast list, except for all-nodes (already installed) */ 2577 2606 2578 - read_lock_bh(&idev->lock); 2579 2607 ipv6_mc_reset(idev); 2580 - for (i = idev->mc_list; i; i = i->next) { 2608 + for_each_mc_rtnl(idev, i) { 2581 2609 mld_del_delrec(idev, i); 2582 2610 igmp6_group_added(i); 2583 2611 } 2584 - read_unlock_bh(&idev->lock); 2585 2612 } 2586 2613 2587 2614 /* IPv6 device initialization. */ 2588 2615 2589 2616 void ipv6_mc_init_dev(struct inet6_dev *idev) 2590 2617 { 2591 - write_lock_bh(&idev->lock); 2592 2618 idev->mc_gq_running = 0; 2593 2619 INIT_DELAYED_WORK(&idev->mc_gq_work, mld_gq_work); 2594 - idev->mc_tomb = NULL; 2620 + RCU_INIT_POINTER(idev->mc_tomb, NULL); 2595 2621 idev->mc_ifc_count = 0; 2596 2622 INIT_DELAYED_WORK(&idev->mc_ifc_work, mld_ifc_work); 2597 2623 INIT_DELAYED_WORK(&idev->mc_dad_work, mld_dad_work); 2598 2624 ipv6_mc_reset(idev); 2599 - write_unlock_bh(&idev->lock); 2600 2625 } 2601 2626 2602 2627 /* ··· 2617 2650 if (idev->cnf.forwarding) 2618 2651 __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters); 2619 2652 2620 - write_lock_bh(&idev->lock); 2621 - while ((i = idev->mc_list) != NULL) { 2622 - idev->mc_list = i->next; 2653 + while ((i = rtnl_dereference(idev->mc_list))) { 2654 + rcu_assign_pointer(idev->mc_list, rtnl_dereference(i->next)); 2623 2655 2624 - write_unlock_bh(&idev->lock); 2625 2656 ip6_mc_clear_src(i); 2626 2657 ma_put(i); 2627 - write_lock_bh(&idev->lock); 2628 2658 } 2629 - write_unlock_bh(&idev->lock); 2630 2659 } 2631 2660 2632 2661 static void ipv6_mc_rejoin_groups(struct inet6_dev *idev) ··· 2632 2669 ASSERT_RTNL(); 2633 2670 2634 2671 if (mld_in_v1_mode(idev)) { 2635 - read_lock_bh(&idev->lock); 2636 - for (pmc = idev->mc_list; pmc; pmc = pmc->next) 2672 + for_each_mc_rtnl(idev, pmc) 2637 2673 igmp6_join_group(pmc); 2638 - read_unlock_bh(&idev->lock); 2639 - } else 2674 + } else { 2640 2675 mld_send_report(idev, NULL); 2676 + } 2641 2677 } 2642 2678 2643 2679 static int ipv6_mc_netdev_event(struct notifier_block *this, ··· 2683 2721 idev = __in6_dev_get(state->dev); 2684 2722 if (!idev) 2685 2723 continue; 2686 - read_lock_bh(&idev->lock); 2687 - im = idev->mc_list; 2724 + 2725 + im = rcu_dereference(idev->mc_list); 2688 2726 if (im) { 2689 2727 state->idev = idev; 2690 2728 break; 2691 2729 } 2692 - read_unlock_bh(&idev->lock); 2693 2730 } 2694 2731 return im; 2695 2732 } ··· 2697 2736 { 2698 2737 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); 2699 2738 2700 - im = im->next; 2739 + im = rcu_dereference(im->next); 2701 2740 while (!im) { 2702 - if (likely(state->idev)) 2703 - read_unlock_bh(&state->idev->lock); 2704 - 2705 2741 state->dev = next_net_device_rcu(state->dev); 2706 2742 if (!state->dev) { 2707 2743 state->idev = NULL; ··· 2707 2749 state->idev = __in6_dev_get(state->dev); 2708 2750 if (!state->idev) 2709 2751 continue; 2710 - read_lock_bh(&state->idev->lock); 2711 - im = state->idev->mc_list; 2752 + im = rcu_dereference(state->idev->mc_list); 2712 2753 } 2713 2754 return im; 2714 2755 } ··· 2741 2784 { 2742 2785 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); 2743 2786 2744 - if (likely(state->idev)) { 2745 - read_unlock_bh(&state->idev->lock); 2787 + if (likely(state->idev)) 2746 2788 state->idev = NULL; 2747 - } 2748 2789 state->dev = NULL; 2749 2790 rcu_read_unlock(); 2750 2791 } ··· 2757 2802 state->dev->ifindex, state->dev->name, 2758 2803 &im->mca_addr, 2759 2804 im->mca_users, im->mca_flags, 2760 - (im->mca_flags&MAF_TIMER_RUNNING) ? 2805 + (im->mca_flags & MAF_TIMER_RUNNING) ? 2761 2806 jiffies_to_clock_t(im->mca_work.timer.expires - jiffies) : 0); 2762 2807 return 0; 2763 2808 } ··· 2792 2837 idev = __in6_dev_get(state->dev); 2793 2838 if (unlikely(idev == NULL)) 2794 2839 continue; 2795 - read_lock_bh(&idev->lock); 2796 - im = idev->mc_list; 2840 + 2841 + im = rcu_dereference(idev->mc_list); 2797 2842 if (likely(im)) { 2798 2843 spin_lock_bh(&im->mca_lock); 2799 2844 psf = rcu_dereference(im->mca_sources); ··· 2804 2849 } 2805 2850 spin_unlock_bh(&im->mca_lock); 2806 2851 } 2807 - read_unlock_bh(&idev->lock); 2808 2852 } 2809 2853 return psf; 2810 2854 } ··· 2815 2861 psf = rcu_dereference(psf->sf_next); 2816 2862 while (!psf) { 2817 2863 spin_unlock_bh(&state->im->mca_lock); 2818 - state->im = state->im->next; 2864 + state->im = rcu_dereference(state->im->next); 2819 2865 while (!state->im) { 2820 - if (likely(state->idev)) 2821 - read_unlock_bh(&state->idev->lock); 2822 - 2823 2866 state->dev = next_net_device_rcu(state->dev); 2824 2867 if (!state->dev) { 2825 2868 state->idev = NULL; ··· 2825 2874 state->idev = __in6_dev_get(state->dev); 2826 2875 if (!state->idev) 2827 2876 continue; 2828 - read_lock_bh(&state->idev->lock); 2829 - state->im = state->idev->mc_list; 2877 + state->im = rcu_dereference(state->idev->mc_list); 2830 2878 } 2831 2879 if (!state->im) 2832 2880 break; ··· 2867 2917 __releases(RCU) 2868 2918 { 2869 2919 struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); 2920 + 2870 2921 if (likely(state->im)) { 2871 2922 spin_unlock_bh(&state->im->mca_lock); 2872 2923 state->im = NULL; 2873 2924 } 2874 - if (likely(state->idev)) { 2875 - read_unlock_bh(&state->idev->lock); 2925 + if (likely(state->idev)) 2876 2926 state->idev = NULL; 2877 - } 2927 + 2878 2928 state->dev = NULL; 2879 2929 rcu_read_unlock(); 2880 2930 }