Commit f3ad4914 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'rtnetlink-rtnl_stats_dump-changes'

Eric Dumazet says:

====================
rtnetlink: rtnl_stats_dump() changes

Getting rid of RTNL in rtnl_stats_dump() looks challenging.

In the meantime, we can:

1) Avoid RTNL acquisition for the final NLMSG_DONE marker.

2) Use for_each_netdev_dump() instead of the net->dev_index_head[]
   hash table.
====================

Link: https://lore.kernel.org/r/20240502113748.1622637-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 5829614a 0feb396f
Loading
Loading
Loading
Loading
+23 −38
Original line number Diff line number Diff line
@@ -5961,19 +5961,17 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct netlink_ext_ack *extack = cb->extack;
	int h, s_h, err, s_idx, s_idxattr, s_prividx;
	struct rtnl_stats_dump_filters filters;
	struct net *net = sock_net(skb->sk);
	unsigned int flags = NLM_F_MULTI;
	struct if_stats_msg *ifsm;
	struct hlist_head *head;
	struct {
		unsigned long ifindex;
		int idxattr;
		int prividx;
	} *ctx = (void *)cb->ctx;
	struct net_device *dev;
	int idx = 0;

	s_h = cb->args[0];
	s_idx = cb->args[1];
	s_idxattr = cb->args[2];
	s_prividx = cb->args[3];
	int err;

	cb->seq = net->dev_base_seq;

@@ -5992,39 +5990,26 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
	if (err)
		return err;

	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
		idx = 0;
		head = &net->dev_index_head[h];
		hlist_for_each_entry(dev, head, index_hlist) {
			if (idx < s_idx)
				goto cont;
	for_each_netdev_dump(net, dev, ctx->ifindex) {
		err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS,
					  NETLINK_CB(cb->skb).portid,
					  cb->nlh->nlmsg_seq, 0,
					  flags, &filters,
						  &s_idxattr, &s_prividx,
					  &ctx->idxattr, &ctx->prividx,
					  extack);
		/* If we ran out of room on the first message,
			 * we're in trouble
		 * we're in trouble.
		 */
		WARN_ON((err == -EMSGSIZE) && (skb->len == 0));

		if (err < 0)
				goto out;
			s_prividx = 0;
			s_idxattr = 0;
			break;
		ctx->prividx = 0;
		ctx->idxattr = 0;
		nl_dump_check_consistent(cb, nlmsg_hdr(skb));
cont:
			idx++;
	}
	}
out:
	cb->args[3] = s_prividx;
	cb->args[2] = s_idxattr;
	cb->args[1] = idx;
	cb->args[0] = h;

	return skb->len;
	return err;
}

void rtnl_offload_xstats_notify(struct net_device *dev)