Skip to content

Commit 88e2ca3

Browse files
TaeheeYoodavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4b200e3 commit 88e2ca3

File tree

7 files changed

+140
-188
lines changed

7 files changed

+140
-188
lines changed

drivers/s390/net/qeth_l3_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,8 +1098,9 @@ static int qeth_l3_add_mcast_rtnl(struct net_device *dev, int vid, void *arg)
10981098
tmp.disp_flag = QETH_DISP_ADDR_ADD;
10991099
tmp.is_multicast = 1;
11001100

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)) {
11031104
tmp.u.a6.addr = im6->mca_addr;
11041105

11051106
ipm = qeth_l3_find_addr_by_ip(card, &tmp);
@@ -1117,7 +1118,6 @@ static int qeth_l3_add_mcast_rtnl(struct net_device *dev, int vid, void *arg)
11171118
qeth_l3_ipaddr_hash(ipm));
11181119

11191120
}
1120-
read_unlock_bh(&in6_dev->lock);
11211121

11221122
out:
11231123
return 0;

include/net/if_inet6.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ struct ip6_sf_list {
115115
struct ifmcaddr6 {
116116
struct in6_addr mca_addr;
117117
struct inet6_dev *idev;
118-
struct ifmcaddr6 *next;
118+
struct ifmcaddr6 __rcu *next;
119119
struct ip6_sf_list __rcu *mca_sources;
120120
struct ip6_sf_list __rcu *mca_tomb;
121121
unsigned int mca_sfmode;
@@ -128,6 +128,7 @@ struct ifmcaddr6 {
128128
spinlock_t mca_lock;
129129
unsigned long mca_cstamp;
130130
unsigned long mca_tstamp;
131+
struct rcu_head rcu;
131132
};
132133

133134
/* Anycast stuff */
@@ -166,8 +167,8 @@ struct inet6_dev {
166167

167168
struct list_head addr_list;
168169

169-
struct ifmcaddr6 *mc_list;
170-
struct ifmcaddr6 *mc_tomb;
170+
struct ifmcaddr6 __rcu *mc_list;
171+
struct ifmcaddr6 __rcu *mc_tomb;
171172

172173
unsigned char mc_qrv; /* Query Robustness Variable */
173174
unsigned char mc_gq_running;

net/batman-adv/multicast.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
454454
return 0;
455455
}
456456

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)) {
459460
if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
460461
IPV6_ADDR_SCOPE_LINKLOCAL)
461462
continue;
@@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
484485
hlist_add_head(&new->list, mcast_list);
485486
ret++;
486487
}
487-
read_unlock_bh(&in6_dev->lock);
488488
rcu_read_unlock();
489489

490490
return ret;

net/ipv6/addrconf.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5107,17 +5107,20 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
51075107
break;
51085108
}
51095109
case MULTICAST_ADDR:
5110+
read_unlock_bh(&idev->lock);
51105111
fillargs->event = RTM_GETMULTICAST;
51115112

51125113
/* 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++) {
51155117
if (ip_idx < s_ip_idx)
51165118
continue;
51175119
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
51185120
if (err < 0)
51195121
break;
51205122
}
5123+
read_lock_bh(&idev->lock);
51215124
break;
51225125
case ANYCAST_ADDR:
51235126
fillargs->event = RTM_GETANYCAST;
@@ -6093,10 +6096,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
60936096

60946097
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
60956098
{
6096-
rcu_read_lock_bh();
60976099
if (likely(ifp->idev->dead == 0))
60986100
__ipv6_ifa_notify(event, ifp);
6099-
rcu_read_unlock_bh();
61006101
}
61016102

61026103
#ifdef CONFIG_SYSCTL

net/ipv6/addrconf_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
250250
struct net_device *dev = idev->dev;
251251

252252
WARN_ON(!list_empty(&idev->addr_list));
253-
WARN_ON(idev->mc_list);
253+
WARN_ON(rcu_access_pointer(idev->mc_list));
254254
WARN_ON(timer_pending(&idev->rs_timer));
255255

256256
#ifdef NET_REFCNT_DEBUG

net/ipv6/af_inet6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
222222
inet->mc_loop = 1;
223223
inet->mc_ttl = 1;
224224
inet->mc_index = 0;
225-
inet->mc_list = NULL;
225+
RCU_INIT_POINTER(inet->mc_list, NULL);
226226
inet->rcv_tos = 0;
227227

228228
if (net->ipv4.sysctl_ip_no_pmtu_disc)

0 commit comments

Comments
 (0)