Commit f3ad4914 authored by Jakub Kicinski's avatar Jakub Kicinski

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.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 5829614a 0feb396f
...@@ -5961,19 +5961,17 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -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) static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
{ {
struct netlink_ext_ack *extack = cb->extack; 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 rtnl_stats_dump_filters filters;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
unsigned int flags = NLM_F_MULTI; unsigned int flags = NLM_F_MULTI;
struct if_stats_msg *ifsm; 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; struct net_device *dev;
int idx = 0; int err;
s_h = cb->args[0];
s_idx = cb->args[1];
s_idxattr = cb->args[2];
s_prividx = cb->args[3];
cb->seq = net->dev_base_seq; cb->seq = net->dev_base_seq;
...@@ -5992,39 +5990,26 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -5992,39 +5990,26 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
if (err) if (err)
return err; return err;
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { for_each_netdev_dump(net, dev, ctx->ifindex) {
idx = 0;
head = &net->dev_index_head[h];
hlist_for_each_entry(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS, err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, 0, cb->nlh->nlmsg_seq, 0,
flags, &filters, flags, &filters,
&s_idxattr, &s_prividx, &ctx->idxattr, &ctx->prividx,
extack); extack);
/* If we ran out of room on the first message, /* 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)); WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
if (err < 0) if (err < 0)
goto out; break;
s_prividx = 0; ctx->prividx = 0;
s_idxattr = 0; ctx->idxattr = 0;
nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 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) void rtnl_offload_xstats_notify(struct net_device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment