Skip to content

Commit

Permalink
IPV4: use rcu to walk list of devices in IGMP
Browse files Browse the repository at this point in the history
This also needs to be optimized for large number of devices.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
stephen hemminger authored and David S. Miller committed Nov 11, 2009
1 parent fa91860 commit 61fbab7
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions net/ipv4/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2311,7 +2311,7 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);

state->in_dev = NULL;
for_each_netdev(net, state->dev) {
for_each_netdev_rcu(net, state->dev) {
struct in_device *in_dev;
in_dev = in_dev_get(state->dev);
if (!in_dev)
Expand Down Expand Up @@ -2361,9 +2361,9 @@ static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos)
}

static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(dev_base_lock)
__acquires(rcu)
{
read_lock(&dev_base_lock);
rcu_read_lock();
return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}

Expand All @@ -2379,7 +2379,7 @@ static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
}

static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
__releases(dev_base_lock)
__releases(rcu)
{
struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
if (likely(state->in_dev != NULL)) {
Expand All @@ -2388,7 +2388,7 @@ static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
state->in_dev = NULL;
}
state->dev = NULL;
read_unlock(&dev_base_lock);
rcu_read_unlock();
}

static int igmp_mc_seq_show(struct seq_file *seq, void *v)
Expand Down Expand Up @@ -2462,7 +2462,7 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)

state->idev = NULL;
state->im = NULL;
for_each_netdev(net, state->dev) {
for_each_netdev_rcu(net, state->dev) {
struct in_device *idev;
idev = in_dev_get(state->dev);
if (unlikely(idev == NULL))
Expand Down Expand Up @@ -2528,8 +2528,9 @@ static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos)
}

static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(rcu)
{
read_lock(&dev_base_lock);
rcu_read_lock();
return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}

Expand All @@ -2545,6 +2546,7 @@ static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
}

static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
__releases(rcu)
{
struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
if (likely(state->im != NULL)) {
Expand All @@ -2557,7 +2559,7 @@ static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
state->idev = NULL;
}
state->dev = NULL;
read_unlock(&dev_base_lock);
rcu_read_unlock();
}

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

0 comments on commit 61fbab7

Please sign in to comment.