diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-11-02 04:43:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-02 06:41:29 -0500 |
commit | 654d1f8a019dfa06df8355248e1ce222f303b88d (patch) | |
tree | a3cc01a84509099099d88cc17bf5c0850355525a | |
parent | 1178f66eaea968d093cafd37c226ebeaa70d56cf (diff) |
packet: less dev_put() calls
- packet_sendmsg_spkt() can use dev_get_by_name_rcu() to avoid touching device refcount.
- packet_getname_spkt() & packet_getname() can use dev_get_by_index_rcu() to
avoid touching device refcount too.
tpacket_snd() & packet_snd() can not use RCU yet because they can sleep when
allocating skb.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/packet/af_packet.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 95ef64e4189a..91d246d34780 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -437,7 +437,8 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
437 | */ | 437 | */ |
438 | 438 | ||
439 | saddr->spkt_device[13] = 0; | 439 | saddr->spkt_device[13] = 0; |
440 | dev = dev_get_by_name(sock_net(sk), saddr->spkt_device); | 440 | rcu_read_lock(); |
441 | dev = dev_get_by_name_rcu(sock_net(sk), saddr->spkt_device); | ||
441 | err = -ENODEV; | 442 | err = -ENODEV; |
442 | if (dev == NULL) | 443 | if (dev == NULL) |
443 | goto out_unlock; | 444 | goto out_unlock; |
@@ -500,14 +501,13 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
500 | */ | 501 | */ |
501 | 502 | ||
502 | dev_queue_xmit(skb); | 503 | dev_queue_xmit(skb); |
503 | dev_put(dev); | 504 | rcu_read_unlock(); |
504 | return len; | 505 | return len; |
505 | 506 | ||
506 | out_free: | 507 | out_free: |
507 | kfree_skb(skb); | 508 | kfree_skb(skb); |
508 | out_unlock: | 509 | out_unlock: |
509 | if (dev) | 510 | rcu_read_unlock(); |
510 | dev_put(dev); | ||
511 | return err; | 511 | return err; |
512 | } | 512 | } |
513 | 513 | ||
@@ -1518,12 +1518,13 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, | |||
1518 | return -EOPNOTSUPP; | 1518 | return -EOPNOTSUPP; |
1519 | 1519 | ||
1520 | uaddr->sa_family = AF_PACKET; | 1520 | uaddr->sa_family = AF_PACKET; |
1521 | dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex); | 1521 | rcu_read_lock(); |
1522 | if (dev) { | 1522 | dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); |
1523 | if (dev) | ||
1523 | strlcpy(uaddr->sa_data, dev->name, 15); | 1524 | strlcpy(uaddr->sa_data, dev->name, 15); |
1524 | dev_put(dev); | 1525 | else |
1525 | } else | ||
1526 | memset(uaddr->sa_data, 0, 14); | 1526 | memset(uaddr->sa_data, 0, 14); |
1527 | rcu_read_unlock(); | ||
1527 | *uaddr_len = sizeof(*uaddr); | 1528 | *uaddr_len = sizeof(*uaddr); |
1528 | 1529 | ||
1529 | return 0; | 1530 | return 0; |
@@ -1543,16 +1544,17 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1543 | sll->sll_family = AF_PACKET; | 1544 | sll->sll_family = AF_PACKET; |
1544 | sll->sll_ifindex = po->ifindex; | 1545 | sll->sll_ifindex = po->ifindex; |
1545 | sll->sll_protocol = po->num; | 1546 | sll->sll_protocol = po->num; |
1546 | dev = dev_get_by_index(sock_net(sk), po->ifindex); | 1547 | rcu_read_lock(); |
1548 | dev = dev_get_by_index_rcu(sock_net(sk), po->ifindex); | ||
1547 | if (dev) { | 1549 | if (dev) { |
1548 | sll->sll_hatype = dev->type; | 1550 | sll->sll_hatype = dev->type; |
1549 | sll->sll_halen = dev->addr_len; | 1551 | sll->sll_halen = dev->addr_len; |
1550 | memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len); | 1552 | memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len); |
1551 | dev_put(dev); | ||
1552 | } else { | 1553 | } else { |
1553 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | 1554 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
1554 | sll->sll_halen = 0; | 1555 | sll->sll_halen = 0; |
1555 | } | 1556 | } |
1557 | rcu_read_unlock(); | ||
1556 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; | 1558 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; |
1557 | 1559 | ||
1558 | return 0; | 1560 | return 0; |