forked from mirrors/linux
		
	rtnetlink: use xarray iterator to implement rtnl_dump_ifinfo()
Adopt net->dev_by_index as I did in commit 0e0939c0ad
("net-procfs: use xarray iterator to implement /proc/net/dev")
This makes sure an existing device is always visible in the dump,
regardless of concurrent insertions/deletions.
v2: added suggestions from Jakub Kicinski and Ido Schimmel,
    thanks for the help !
Link: https://lore.kernel.org/all/20240209142441.6c56435b@kernel.org/
Link: https://lore.kernel.org/all/ZckR-XOsULLI9EHc@shredder/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/20240211214404.1882191-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									f383ced24d
								
							
						
					
					
						commit
						3e41af9076
					
				
					 1 changed files with 21 additions and 39 deletions
				
			
		|  | @ -2188,25 +2188,22 @@ static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh, | |||
| 
 | ||||
| static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | ||||
| { | ||||
| 	const struct rtnl_link_ops *kind_ops = NULL; | ||||
| 	struct netlink_ext_ack *extack = cb->extack; | ||||
| 	const struct nlmsghdr *nlh = cb->nlh; | ||||
| 	struct net *net = sock_net(skb->sk); | ||||
| 	struct net *tgt_net = net; | ||||
| 	int h, s_h; | ||||
| 	int idx = 0, s_idx; | ||||
| 	struct net_device *dev; | ||||
| 	struct hlist_head *head; | ||||
| 	struct nlattr *tb[IFLA_MAX+1]; | ||||
| 	u32 ext_filter_mask = 0; | ||||
| 	const struct rtnl_link_ops *kind_ops = NULL; | ||||
| 	unsigned int flags = NLM_F_MULTI; | ||||
| 	struct nlattr *tb[IFLA_MAX+1]; | ||||
| 	struct { | ||||
| 		unsigned long ifindex; | ||||
| 	} *ctx = (void *)cb->ctx; | ||||
| 	struct net *tgt_net = net; | ||||
| 	u32 ext_filter_mask = 0; | ||||
| 	struct net_device *dev; | ||||
| 	int master_idx = 0; | ||||
| 	int netnsid = -1; | ||||
| 	int err, i; | ||||
| 
 | ||||
| 	s_h = cb->args[0]; | ||||
| 	s_idx = cb->args[1]; | ||||
| 
 | ||||
| 	err = rtnl_valid_dump_ifinfo_req(nlh, cb->strict_check, tb, extack); | ||||
| 	if (err < 0) { | ||||
| 		if (cb->strict_check) | ||||
|  | @ -2250,36 +2247,21 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 		flags |= NLM_F_DUMP_FILTERED; | ||||
| 
 | ||||
| walk_entries: | ||||
| 	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||||
| 		idx = 0; | ||||
| 		head = &tgt_net->dev_index_head[h]; | ||||
| 		hlist_for_each_entry(dev, head, index_hlist) { | ||||
| 	err = 0; | ||||
| 	for_each_netdev_dump(tgt_net, dev, ctx->ifindex) { | ||||
| 		if (link_dump_filtered(dev, master_idx, kind_ops)) | ||||
| 				goto cont; | ||||
| 			if (idx < s_idx) | ||||
| 				goto cont; | ||||
| 			err = rtnl_fill_ifinfo(skb, dev, net, | ||||
| 					       RTM_NEWLINK, | ||||
| 			continue; | ||||
| 		err = rtnl_fill_ifinfo(skb, dev, net, RTM_NEWLINK, | ||||
| 				       NETLINK_CB(cb->skb).portid, | ||||
| 				       nlh->nlmsg_seq, 0, flags, | ||||
| 				       ext_filter_mask, 0, NULL, 0, | ||||
| 				       netnsid, GFP_KERNEL); | ||||
| 
 | ||||
| 		if (err < 0) { | ||||
| 			if (likely(skb->len)) | ||||
| 					goto out; | ||||
| 
 | ||||
| 				goto out_err; | ||||
| 			} | ||||
| cont: | ||||
| 			idx++; | ||||
| 		} | ||||
| 	} | ||||
| out: | ||||
| 				err = skb->len; | ||||
| out_err: | ||||
| 	cb->args[1] = idx; | ||||
| 	cb->args[0] = h; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	cb->seq = tgt_net->dev_base_seq; | ||||
| 	nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||||
| 	if (netnsid >= 0) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Eric Dumazet
						Eric Dumazet