mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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>
This commit is contained in:
committed by
David S. Miller
parent
4b200e3989
commit
88e2ca3080
@@ -1098,8 +1098,9 @@ walk_ipv6:
|
||||
tmp.disp_flag = QETH_DISP_ADDR_ADD;
|
||||
tmp.is_multicast = 1;
|
||||
|
||||
read_lock_bh(&in6_dev->lock);
|
||||
for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
|
||||
for (im6 = rtnl_dereference(in6_dev->mc_list);
|
||||
im6;
|
||||
im6 = rtnl_dereference(im6->next)) {
|
||||
tmp.u.a6.addr = im6->mca_addr;
|
||||
|
||||
ipm = qeth_l3_find_addr_by_ip(card, &tmp);
|
||||
@@ -1117,7 +1118,6 @@ walk_ipv6:
|
||||
qeth_l3_ipaddr_hash(ipm));
|
||||
|
||||
}
|
||||
read_unlock_bh(&in6_dev->lock);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
@@ -115,7 +115,7 @@ struct ip6_sf_list {
|
||||
struct ifmcaddr6 {
|
||||
struct in6_addr mca_addr;
|
||||
struct inet6_dev *idev;
|
||||
struct ifmcaddr6 *next;
|
||||
struct ifmcaddr6 __rcu *next;
|
||||
struct ip6_sf_list __rcu *mca_sources;
|
||||
struct ip6_sf_list __rcu *mca_tomb;
|
||||
unsigned int mca_sfmode;
|
||||
@@ -128,6 +128,7 @@ struct ifmcaddr6 {
|
||||
spinlock_t mca_lock;
|
||||
unsigned long mca_cstamp;
|
||||
unsigned long mca_tstamp;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/* Anycast stuff */
|
||||
@@ -166,8 +167,8 @@ struct inet6_dev {
|
||||
|
||||
struct list_head addr_list;
|
||||
|
||||
struct ifmcaddr6 *mc_list;
|
||||
struct ifmcaddr6 *mc_tomb;
|
||||
struct ifmcaddr6 __rcu *mc_list;
|
||||
struct ifmcaddr6 __rcu *mc_tomb;
|
||||
|
||||
unsigned char mc_qrv; /* Query Robustness Variable */
|
||||
unsigned char mc_gq_running;
|
||||
|
||||
@@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_lock_bh(&in6_dev->lock);
|
||||
for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
|
||||
for (pmc6 = rcu_dereference(in6_dev->mc_list);
|
||||
pmc6;
|
||||
pmc6 = rcu_dereference(pmc6->next)) {
|
||||
if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
|
||||
IPV6_ADDR_SCOPE_LINKLOCAL)
|
||||
continue;
|
||||
@@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
|
||||
hlist_add_head(&new->list, mcast_list);
|
||||
ret++;
|
||||
}
|
||||
read_unlock_bh(&in6_dev->lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -5107,17 +5107,20 @@ next:
|
||||
break;
|
||||
}
|
||||
case MULTICAST_ADDR:
|
||||
read_unlock_bh(&idev->lock);
|
||||
fillargs->event = RTM_GETMULTICAST;
|
||||
|
||||
/* multicast address */
|
||||
for (ifmca = idev->mc_list; ifmca;
|
||||
ifmca = ifmca->next, ip_idx++) {
|
||||
for (ifmca = rcu_dereference(idev->mc_list);
|
||||
ifmca;
|
||||
ifmca = rcu_dereference(ifmca->next), ip_idx++) {
|
||||
if (ip_idx < s_ip_idx)
|
||||
continue;
|
||||
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
read_lock_bh(&idev->lock);
|
||||
break;
|
||||
case ANYCAST_ADDR:
|
||||
fillargs->event = RTM_GETANYCAST;
|
||||
@@ -6093,10 +6096,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
|
||||
|
||||
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
|
||||
{
|
||||
rcu_read_lock_bh();
|
||||
if (likely(ifp->idev->dead == 0))
|
||||
__ipv6_ifa_notify(event, ifp);
|
||||
rcu_read_unlock_bh();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
@@ -250,7 +250,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
|
||||
struct net_device *dev = idev->dev;
|
||||
|
||||
WARN_ON(!list_empty(&idev->addr_list));
|
||||
WARN_ON(idev->mc_list);
|
||||
WARN_ON(rcu_access_pointer(idev->mc_list));
|
||||
WARN_ON(timer_pending(&idev->rs_timer));
|
||||
|
||||
#ifdef NET_REFCNT_DEBUG
|
||||
|
||||
@@ -222,7 +222,7 @@ lookup_protocol:
|
||||
inet->mc_loop = 1;
|
||||
inet->mc_ttl = 1;
|
||||
inet->mc_index = 0;
|
||||
inet->mc_list = NULL;
|
||||
RCU_INIT_POINTER(inet->mc_list, NULL);
|
||||
inet->rcv_tos = 0;
|
||||
|
||||
if (net->ipv4.sysctl_ip_no_pmtu_disc)
|
||||
|
||||
296
net/ipv6/mcast.c
296
net/ipv6/mcast.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user