Skip to content

Commit

Permalink
vlan: use xarray iterator to implement /proc/net/vlan/config
Browse files Browse the repository at this point in the history
Adopt net->dev_by_index as I did in commit 0e0939c
("net-procfs: use xarray iterator to implement /proc/net/dev")

Not only this removes quadratic behavior, it also makes sure
an existing vlan device is always visible in the dump,
regardless of concurrent net->dev_base_head changes.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/20240211214404.1882191-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Eric Dumazet authored and Jakub Kicinski committed Feb 14, 2024
1 parent bed90b0 commit f383ced
Showing 1 changed file with 16 additions and 30 deletions.
46 changes: 16 additions & 30 deletions net/8021q/vlanproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,48 +163,34 @@ void vlan_proc_rem_dev(struct net_device *vlandev)
* The following few functions build the content of /proc/net/vlan/config
*/

/* start read of /proc/net/vlan/config */
static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(rcu)
static void *vlan_seq_from_index(struct seq_file *seq, loff_t *pos)
{
unsigned long ifindex = *pos;
struct net_device *dev;
struct net *net = seq_file_net(seq);
loff_t i = 1;

rcu_read_lock();
if (*pos == 0)
return SEQ_START_TOKEN;

for_each_netdev_rcu(net, dev) {
for_each_netdev_dump(seq_file_net(seq), dev, ifindex) {
if (!is_vlan_dev(dev))
continue;

if (i++ == *pos)
return dev;
*pos = dev->ifindex;
return dev;
}
return NULL;
}

static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(rcu)
{
rcu_read_lock();
if (*pos == 0)
return SEQ_START_TOKEN;

return NULL;
return vlan_seq_from_index(seq, pos);
}

static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct net_device *dev;
struct net *net = seq_file_net(seq);

++*pos;

dev = v;
if (v == SEQ_START_TOKEN)
dev = net_device_entry(&net->dev_base_head);

for_each_netdev_continue_rcu(net, dev) {
if (!is_vlan_dev(dev))
continue;

return dev;
}

return NULL;
return vlan_seq_from_index(seq, pos);
}

static void vlan_seq_stop(struct seq_file *seq, void *v)
Expand Down

0 comments on commit f383ced

Please sign in to comment.