diff options
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 50 |
1 files changed, 24 insertions, 26 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d41e5de79a82..76c08402c933 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1899,8 +1899,9 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1899 | err = -EADDRNOTAVAIL; | 1899 | err = -EADDRNOTAVAIL; |
1900 | 1900 | ||
1901 | for (pmc=inet->mc_list; pmc; pmc=pmc->next) { | 1901 | for (pmc=inet->mc_list; pmc; pmc=pmc->next) { |
1902 | if (pmc->multi.imr_multiaddr.s_addr == imr.imr_multiaddr.s_addr | 1902 | if ((pmc->multi.imr_multiaddr.s_addr == |
1903 | && pmc->multi.imr_ifindex == imr.imr_ifindex) | 1903 | imr.imr_multiaddr.s_addr) && |
1904 | (pmc->multi.imr_ifindex == imr.imr_ifindex)) | ||
1904 | break; | 1905 | break; |
1905 | } | 1906 | } |
1906 | if (!pmc) { /* must have a prior join */ | 1907 | if (!pmc) { /* must have a prior join */ |
@@ -2311,9 +2312,10 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq) | |||
2311 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); | 2312 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); |
2312 | 2313 | ||
2313 | state->in_dev = NULL; | 2314 | state->in_dev = NULL; |
2314 | for_each_netdev(net, state->dev) { | 2315 | for_each_netdev_rcu(net, state->dev) { |
2315 | struct in_device *in_dev; | 2316 | struct in_device *in_dev; |
2316 | in_dev = in_dev_get(state->dev); | 2317 | |
2318 | in_dev = __in_dev_get_rcu(state->dev); | ||
2317 | if (!in_dev) | 2319 | if (!in_dev) |
2318 | continue; | 2320 | continue; |
2319 | read_lock(&in_dev->mc_list_lock); | 2321 | read_lock(&in_dev->mc_list_lock); |
@@ -2323,7 +2325,6 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq) | |||
2323 | break; | 2325 | break; |
2324 | } | 2326 | } |
2325 | read_unlock(&in_dev->mc_list_lock); | 2327 | read_unlock(&in_dev->mc_list_lock); |
2326 | in_dev_put(in_dev); | ||
2327 | } | 2328 | } |
2328 | return im; | 2329 | return im; |
2329 | } | 2330 | } |
@@ -2333,16 +2334,15 @@ static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_li | |||
2333 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); | 2334 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); |
2334 | im = im->next; | 2335 | im = im->next; |
2335 | while (!im) { | 2336 | while (!im) { |
2336 | if (likely(state->in_dev != NULL)) { | 2337 | if (likely(state->in_dev != NULL)) |
2337 | read_unlock(&state->in_dev->mc_list_lock); | 2338 | read_unlock(&state->in_dev->mc_list_lock); |
2338 | in_dev_put(state->in_dev); | 2339 | |
2339 | } | 2340 | state->dev = next_net_device_rcu(state->dev); |
2340 | state->dev = next_net_device(state->dev); | ||
2341 | if (!state->dev) { | 2341 | if (!state->dev) { |
2342 | state->in_dev = NULL; | 2342 | state->in_dev = NULL; |
2343 | break; | 2343 | break; |
2344 | } | 2344 | } |
2345 | state->in_dev = in_dev_get(state->dev); | 2345 | state->in_dev = __in_dev_get_rcu(state->dev); |
2346 | if (!state->in_dev) | 2346 | if (!state->in_dev) |
2347 | continue; | 2347 | continue; |
2348 | read_lock(&state->in_dev->mc_list_lock); | 2348 | read_lock(&state->in_dev->mc_list_lock); |
@@ -2361,9 +2361,9 @@ static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos) | |||
2361 | } | 2361 | } |
2362 | 2362 | ||
2363 | static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos) | 2363 | static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos) |
2364 | __acquires(dev_base_lock) | 2364 | __acquires(rcu) |
2365 | { | 2365 | { |
2366 | read_lock(&dev_base_lock); | 2366 | rcu_read_lock(); |
2367 | return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 2367 | return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
2368 | } | 2368 | } |
2369 | 2369 | ||
@@ -2379,16 +2379,15 @@ static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2379 | } | 2379 | } |
2380 | 2380 | ||
2381 | static void igmp_mc_seq_stop(struct seq_file *seq, void *v) | 2381 | static void igmp_mc_seq_stop(struct seq_file *seq, void *v) |
2382 | __releases(dev_base_lock) | 2382 | __releases(rcu) |
2383 | { | 2383 | { |
2384 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); | 2384 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); |
2385 | if (likely(state->in_dev != NULL)) { | 2385 | if (likely(state->in_dev != NULL)) { |
2386 | read_unlock(&state->in_dev->mc_list_lock); | 2386 | read_unlock(&state->in_dev->mc_list_lock); |
2387 | in_dev_put(state->in_dev); | ||
2388 | state->in_dev = NULL; | 2387 | state->in_dev = NULL; |
2389 | } | 2388 | } |
2390 | state->dev = NULL; | 2389 | state->dev = NULL; |
2391 | read_unlock(&dev_base_lock); | 2390 | rcu_read_unlock(); |
2392 | } | 2391 | } |
2393 | 2392 | ||
2394 | static int igmp_mc_seq_show(struct seq_file *seq, void *v) | 2393 | static int igmp_mc_seq_show(struct seq_file *seq, void *v) |
@@ -2462,9 +2461,9 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq) | |||
2462 | 2461 | ||
2463 | state->idev = NULL; | 2462 | state->idev = NULL; |
2464 | state->im = NULL; | 2463 | state->im = NULL; |
2465 | for_each_netdev(net, state->dev) { | 2464 | for_each_netdev_rcu(net, state->dev) { |
2466 | struct in_device *idev; | 2465 | struct in_device *idev; |
2467 | idev = in_dev_get(state->dev); | 2466 | idev = __in_dev_get_rcu(state->dev); |
2468 | if (unlikely(idev == NULL)) | 2467 | if (unlikely(idev == NULL)) |
2469 | continue; | 2468 | continue; |
2470 | read_lock(&idev->mc_list_lock); | 2469 | read_lock(&idev->mc_list_lock); |
@@ -2480,7 +2479,6 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq) | |||
2480 | spin_unlock_bh(&im->lock); | 2479 | spin_unlock_bh(&im->lock); |
2481 | } | 2480 | } |
2482 | read_unlock(&idev->mc_list_lock); | 2481 | read_unlock(&idev->mc_list_lock); |
2483 | in_dev_put(idev); | ||
2484 | } | 2482 | } |
2485 | return psf; | 2483 | return psf; |
2486 | } | 2484 | } |
@@ -2494,16 +2492,15 @@ static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_l | |||
2494 | spin_unlock_bh(&state->im->lock); | 2492 | spin_unlock_bh(&state->im->lock); |
2495 | state->im = state->im->next; | 2493 | state->im = state->im->next; |
2496 | while (!state->im) { | 2494 | while (!state->im) { |
2497 | if (likely(state->idev != NULL)) { | 2495 | if (likely(state->idev != NULL)) |
2498 | read_unlock(&state->idev->mc_list_lock); | 2496 | read_unlock(&state->idev->mc_list_lock); |
2499 | in_dev_put(state->idev); | 2497 | |
2500 | } | 2498 | state->dev = next_net_device_rcu(state->dev); |
2501 | state->dev = next_net_device(state->dev); | ||
2502 | if (!state->dev) { | 2499 | if (!state->dev) { |
2503 | state->idev = NULL; | 2500 | state->idev = NULL; |
2504 | goto out; | 2501 | goto out; |
2505 | } | 2502 | } |
2506 | state->idev = in_dev_get(state->dev); | 2503 | state->idev = __in_dev_get_rcu(state->dev); |
2507 | if (!state->idev) | 2504 | if (!state->idev) |
2508 | continue; | 2505 | continue; |
2509 | read_lock(&state->idev->mc_list_lock); | 2506 | read_lock(&state->idev->mc_list_lock); |
@@ -2528,8 +2525,9 @@ static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos) | |||
2528 | } | 2525 | } |
2529 | 2526 | ||
2530 | static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos) | 2527 | static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos) |
2528 | __acquires(rcu) | ||
2531 | { | 2529 | { |
2532 | read_lock(&dev_base_lock); | 2530 | rcu_read_lock(); |
2533 | return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 2531 | return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
2534 | } | 2532 | } |
2535 | 2533 | ||
@@ -2545,6 +2543,7 @@ static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2545 | } | 2543 | } |
2546 | 2544 | ||
2547 | static void igmp_mcf_seq_stop(struct seq_file *seq, void *v) | 2545 | static void igmp_mcf_seq_stop(struct seq_file *seq, void *v) |
2546 | __releases(rcu) | ||
2548 | { | 2547 | { |
2549 | struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq); | 2548 | struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq); |
2550 | if (likely(state->im != NULL)) { | 2549 | if (likely(state->im != NULL)) { |
@@ -2553,11 +2552,10 @@ static void igmp_mcf_seq_stop(struct seq_file *seq, void *v) | |||
2553 | } | 2552 | } |
2554 | if (likely(state->idev != NULL)) { | 2553 | if (likely(state->idev != NULL)) { |
2555 | read_unlock(&state->idev->mc_list_lock); | 2554 | read_unlock(&state->idev->mc_list_lock); |
2556 | in_dev_put(state->idev); | ||
2557 | state->idev = NULL; | 2555 | state->idev = NULL; |
2558 | } | 2556 | } |
2559 | state->dev = NULL; | 2557 | state->dev = NULL; |
2560 | read_unlock(&dev_base_lock); | 2558 | rcu_read_unlock(); |
2561 | } | 2559 | } |
2562 | 2560 | ||
2563 | static int igmp_mcf_seq_show(struct seq_file *seq, void *v) | 2561 | static int igmp_mcf_seq_show(struct seq_file *seq, void *v) |