aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/icmp.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-07-27 17:13:03 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-01 03:12:00 -0400
commitcfdf76474e1d8a56ac6cfae39f8559cfe9dfd7fd (patch)
treed5fe707a1e8018643cf82f0272e651ceda53a119 /net/ipv6/icmp.c
parentab1594e92e6765fd4af316f130eea8f5c920823d (diff)
ipv6: some RCU conversions
ICMP and ND are not fast path, but still we can avoid changing idev refcount, using RCU. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r--net/ipv6/icmp.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 11900417b1cc..2b59154c65d3 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -490,7 +490,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
490 goto out_dst_release; 490 goto out_dst_release;
491 } 491 }
492 492
493 idev = in6_dev_get(skb->dev); 493 rcu_read_lock();
494 idev = __in6_dev_get(skb->dev);
494 495
495 err = ip6_append_data(sk, icmpv6_getfrag, &msg, 496 err = ip6_append_data(sk, icmpv6_getfrag, &msg,
496 len + sizeof(struct icmp6hdr), 497 len + sizeof(struct icmp6hdr),
@@ -500,19 +501,16 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
500 if (err) { 501 if (err) {
501 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); 502 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
502 ip6_flush_pending_frames(sk); 503 ip6_flush_pending_frames(sk);
503 goto out_put; 504 } else {
505 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
506 len + sizeof(struct icmp6hdr));
504 } 507 }
505 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr)); 508 rcu_read_unlock();
506
507out_put:
508 if (likely(idev != NULL))
509 in6_dev_put(idev);
510out_dst_release: 509out_dst_release:
511 dst_release(dst); 510 dst_release(dst);
512out: 511out:
513 icmpv6_xmit_unlock(sk); 512 icmpv6_xmit_unlock(sk);
514} 513}
515
516EXPORT_SYMBOL(icmpv6_send); 514EXPORT_SYMBOL(icmpv6_send);
517 515
518static void icmpv6_echo_reply(struct sk_buff *skb) 516static void icmpv6_echo_reply(struct sk_buff *skb)
@@ -569,7 +567,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
569 if (hlimit < 0) 567 if (hlimit < 0)
570 hlimit = ip6_dst_hoplimit(dst); 568 hlimit = ip6_dst_hoplimit(dst);
571 569
572 idev = in6_dev_get(skb->dev); 570 idev = __in6_dev_get(skb->dev);
573 571
574 msg.skb = skb; 572 msg.skb = skb;
575 msg.offset = 0; 573 msg.offset = 0;
@@ -583,13 +581,10 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
583 if (err) { 581 if (err) {
584 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); 582 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
585 ip6_flush_pending_frames(sk); 583 ip6_flush_pending_frames(sk);
586 goto out_put; 584 } else {
585 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
586 skb->len + sizeof(struct icmp6hdr));
587 } 587 }
588 err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
589
590out_put:
591 if (likely(idev != NULL))
592 in6_dev_put(idev);
593 dst_release(dst); 588 dst_release(dst);
594out: 589out:
595 icmpv6_xmit_unlock(sk); 590 icmpv6_xmit_unlock(sk);