Skip to content

Commit

Permalink
net-procfs: use xarray iterator to implement /proc/net/dev
Browse files Browse the repository at this point in the history
In commit 759ab1e ("net: store netdevs in an xarray")
Jakub added net->dev_by_index to map ifindex to netdevices.

We can get rid of the old hash table (net->dev_index_head),
one patch at a time, if performance is acceptable.

This patch removes unpleasant code to something more readable.

As a bonus, /proc/net/dev gets netdevices sorted by their ifindex.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20240207165318.3814525-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Eric Dumazet authored and Jakub Kicinski committed Feb 9, 2024
1 parent 6fb5dfe commit 0e0939c
Showing 1 changed file with 7 additions and 41 deletions.
48 changes: 7 additions & 41 deletions net/core/net-procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,66 +6,32 @@

#include "dev.h"

#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1)

#define get_bucket(x) ((x) >> BUCKET_SPACE)
#define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1))
#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))

static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos)
static void *dev_seq_from_index(struct seq_file *seq, loff_t *pos)
{
struct net *net = seq_file_net(seq);
unsigned long ifindex = *pos;
struct net_device *dev;
struct hlist_head *h;
unsigned int count = 0, offset = get_offset(*pos);

h = &net->dev_index_head[get_bucket(*pos)];
hlist_for_each_entry_rcu(dev, h, index_hlist) {
if (++count == offset)
return dev;
for_each_netdev_dump(seq_file_net(seq), dev, ifindex) {
*pos = dev->ifindex;
return dev;
}

return NULL;
}

static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos)
{
struct net_device *dev;
unsigned int bucket;

do {
dev = dev_from_same_bucket(seq, pos);
if (dev)
return dev;

bucket = get_bucket(*pos) + 1;
*pos = set_bucket_offset(bucket, 1);
} while (bucket < NETDEV_HASHENTRIES);

return NULL;
}

/*
* This is invoked by the /proc filesystem handler to display a device
* in detail.
*/
static void *dev_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{
rcu_read_lock();
if (!*pos)
return SEQ_START_TOKEN;

if (get_bucket(*pos) >= NETDEV_HASHENTRIES)
return NULL;

return dev_from_bucket(seq, pos);
return dev_seq_from_index(seq, pos);
}

static void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
++*pos;
return dev_from_bucket(seq, pos);
return dev_seq_from_index(seq, pos);
}

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

0 comments on commit 0e0939c

Please sign in to comment.