aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet/dn_dev.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-04-27 18:56:07 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-02 18:26:28 -0400
commite67f88dd12f610da98ca838822f2c9b4e7c6100e (patch)
tree6cf01b794984aaad97b6e6ff6e5103bc48d68191 /net/decnet/dn_dev.c
parentdcfd9cdc1222f14d6180514e533289493a0716fb (diff)
net: dont hold rtnl mutex during netlink dump callbacks
Four years ago, Patrick made a change to hold rtnl mutex during netlink dump callbacks. I believe it was a wrong move. This slows down concurrent dumps, making good old /proc/net/ files faster than rtnetlink in some situations. This occurred to me because one "ip link show dev ..." was _very_ slow on a workload adding/removing network devices in background. All dump callbacks are able to use RCU locking now, so this patch does roughly a revert of commits : 1c2d670f366 : [RTNETLINK]: Hold rtnl_mutex during netlink dump callbacks 6313c1e0992 : [RTNETLINK]: Remove unnecessary locking in dump callbacks This let writers fight for rtnl mutex and readers going full speed. It also takes care of phonet : phonet_route_get() is now called from rcu read section. I renamed it to phonet_route_get_rcu() Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Cc: Patrick McHardy <kaber@trash.net> Cc: Remi Denis-Courmont <remi.denis-courmont@nokia.com> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/decnet/dn_dev.c')
-rw-r--r--net/decnet/dn_dev.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 0dcaa903e00e..404fa1591027 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -752,7 +752,8 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
752 skip_naddr = cb->args[1]; 752 skip_naddr = cb->args[1];
753 753
754 idx = 0; 754 idx = 0;
755 for_each_netdev(&init_net, dev) { 755 rcu_read_lock();
756 for_each_netdev_rcu(&init_net, dev) {
756 if (idx < skip_ndevs) 757 if (idx < skip_ndevs)
757 goto cont; 758 goto cont;
758 else if (idx > skip_ndevs) { 759 else if (idx > skip_ndevs) {
@@ -761,11 +762,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
761 skip_naddr = 0; 762 skip_naddr = 0;
762 } 763 }
763 764
764 if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) 765 if ((dn_db = rcu_dereference(dev->dn_ptr)) == NULL)
765 goto cont; 766 goto cont;
766 767
767 for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa; 768 for (ifa = rcu_dereference(dn_db->ifa_list), dn_idx = 0; ifa;
768 ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) { 769 ifa = rcu_dereference(ifa->ifa_next), dn_idx++) {
769 if (dn_idx < skip_naddr) 770 if (dn_idx < skip_naddr)
770 continue; 771 continue;
771 772
@@ -778,6 +779,7 @@ cont:
778 idx++; 779 idx++;
779 } 780 }
780done: 781done:
782 rcu_read_unlock();
781 cb->args[0] = idx; 783 cb->args[0] = idx;
782 cb->args[1] = dn_idx; 784 cb->args[1] = dn_idx;
783 785