Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6313c1e0 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[RTNETLINK]: Remove unnecessary locking in dump callbacks



Since we're now holding the rtnl during the entire dump operation, we can
remove additional locking for rtnl protected data. This patch does that
for all simple cases (dev_base_lock for dev_base walking, RCU protection
for FIB rule dumping).

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1c2d670f
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -109,7 +109,6 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
	struct net_device *dev;
	struct net_device *dev;
	int idx;
	int idx;


	read_lock(&dev_base_lock);
	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
		/* not a bridge port */
		/* not a bridge port */
		if (dev->br_port == NULL || idx < cb->args[0])
		if (dev->br_port == NULL || idx < cb->args[0])
@@ -122,7 +121,6 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
skip:
skip:
		++idx;
		++idx;
	}
	}
	read_unlock(&dev_base_lock);


	cb->args[0] = idx;
	cb->args[0] = idx;


+1 −3
Original line number Original line Diff line number Diff line
@@ -495,8 +495,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
	int idx = 0;
	int idx = 0;
	struct fib_rule *rule;
	struct fib_rule *rule;


	rcu_read_lock();
	list_for_each_entry(rule, ops->rules_list, list) {
	list_for_each_entry_rcu(rule, ops->rules_list, list) {
		if (idx < cb->args[1])
		if (idx < cb->args[1])
			goto skip;
			goto skip;


@@ -507,7 +506,6 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
skip:
skip:
		idx++;
		idx++;
	}
	}
	rcu_read_unlock();
	cb->args[1] = idx;
	cb->args[1] = idx;
	rules_ops_put(ops);
	rules_ops_put(ops);


+0 −2
Original line number Original line Diff line number Diff line
@@ -543,7 +543,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
	int s_idx = cb->args[0];
	int s_idx = cb->args[0];
	struct net_device *dev;
	struct net_device *dev;


	read_lock(&dev_base_lock);
	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
		if (idx < s_idx)
		if (idx < s_idx)
			continue;
			continue;
@@ -552,7 +551,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
				     cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
				     cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
			break;
			break;
	}
	}
	read_unlock(&dev_base_lock);
	cb->args[0] = idx;
	cb->args[0] = idx;


	return skb->len;
	return skb->len;
+0 −3
Original line number Original line Diff line number Diff line
@@ -799,7 +799,6 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
	skip_ndevs = cb->args[0];
	skip_ndevs = cb->args[0];
	skip_naddr = cb->args[1];
	skip_naddr = cb->args[1];


	read_lock(&dev_base_lock);
	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
		if (idx < skip_ndevs)
		if (idx < skip_ndevs)
			continue;
			continue;
@@ -824,8 +823,6 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
		}
		}
	}
	}
done:
done:
	read_unlock(&dev_base_lock);

	cb->args[0] = idx;
	cb->args[0] = idx;
	cb->args[1] = dn_idx;
	cb->args[1] = dn_idx;


+2 −10
Original line number Original line Diff line number Diff line
@@ -1182,17 +1182,13 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
	int s_ip_idx, s_idx = cb->args[0];
	int s_ip_idx, s_idx = cb->args[0];


	s_ip_idx = ip_idx = cb->args[1];
	s_ip_idx = ip_idx = cb->args[1];
	read_lock(&dev_base_lock);
	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
		if (idx < s_idx)
		if (idx < s_idx)
			continue;
			continue;
		if (idx > s_idx)
		if (idx > s_idx)
			s_ip_idx = 0;
			s_ip_idx = 0;
		rcu_read_lock();
		if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
		if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
			rcu_read_unlock();
			continue;
			continue;
		}


		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
		     ifa = ifa->ifa_next, ip_idx++) {
		     ifa = ifa->ifa_next, ip_idx++) {
@@ -1200,16 +1196,12 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
				continue;
				continue;
			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
					     cb->nlh->nlmsg_seq,
					     cb->nlh->nlmsg_seq,
					     RTM_NEWADDR, NLM_F_MULTI) <= 0) {
					     RTM_NEWADDR, NLM_F_MULTI) <= 0)
				rcu_read_unlock();
				goto done;
				goto done;
		}
		}
	}
	}
		rcu_read_unlock();
	}


done:
done:
	read_unlock(&dev_base_lock);
	cb->args[0] = idx;
	cb->args[0] = idx;
	cb->args[1] = ip_idx;
	cb->args[1] = ip_idx;


Loading