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

net: Revert "ipv4: fix a deadlock in ip_ra_control"

This reverts commit 1215e51edad1.
Since raw_close() is used on every RAW socket destruction,
the changes made by 1215e51edad1 scale sadly. This clearly
seen on endless unshare(CLONE_NEWNET) test, and cleanup_net()
kwork spends a lot of time waiting for rtnl_lock() introduced
by this commit.

Previous patch moved IP_ROUTER_ALERT out of rtnl_lock(),
so we revert this patch.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kirill Tkhai and committed by
David S. Miller
128aaa98 0526947f

+9 -5
-1
net/ipv4/ip_sockglue.c
··· 594 594 case MCAST_LEAVE_GROUP: 595 595 case MCAST_LEAVE_SOURCE_GROUP: 596 596 case MCAST_UNBLOCK_SOURCE: 597 - case IP_ROUTER_ALERT: 598 597 return true; 599 598 } 600 599 return false;
+9 -2
net/ipv4/ipmr.c
··· 1399 1399 struct net *net = sock_net(sk); 1400 1400 struct mr_table *mrt; 1401 1401 1402 - ASSERT_RTNL(); 1402 + rtnl_lock(); 1403 1403 ipmr_for_each_table(mrt, net) { 1404 1404 if (sk == rtnl_dereference(mrt->mroute_sk)) { 1405 1405 IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; ··· 1411 1411 mroute_clean_tables(mrt, false); 1412 1412 } 1413 1413 } 1414 + rtnl_unlock(); 1414 1415 } 1415 1416 1416 1417 /* Socket options and virtual interface manipulation. The whole ··· 1476 1475 if (sk != rcu_access_pointer(mrt->mroute_sk)) { 1477 1476 ret = -EACCES; 1478 1477 } else { 1478 + /* We need to unlock here because mrtsock_destruct takes 1479 + * care of rtnl itself and we can't change that due to 1480 + * the IP_ROUTER_ALERT setsockopt which runs without it. 1481 + */ 1482 + rtnl_unlock(); 1479 1483 ret = ip_ra_control(sk, 0, NULL); 1480 - goto out_unlock; 1484 + goto out; 1481 1485 } 1482 1486 break; 1483 1487 case MRT_ADD_VIF: ··· 1594 1588 } 1595 1589 out_unlock: 1596 1590 rtnl_unlock(); 1591 + out: 1597 1592 return ret; 1598 1593 } 1599 1594
-2
net/ipv4/raw.c
··· 711 711 /* 712 712 * Raw sockets may have direct kernel references. Kill them. 713 713 */ 714 - rtnl_lock(); 715 714 ip_ra_control(sk, 0, NULL); 716 - rtnl_unlock(); 717 715 718 716 sk_common_release(sk); 719 717 }