diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index bec01a3daf5b..2986941164b1 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1769,7 +1769,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
1769 | 1769 | ||
1770 | out: | 1770 | out: |
1771 | if (err && rollover) { | 1771 | if (err && rollover) { |
1772 | kfree(rollover); | 1772 | kfree_rcu(rollover, rcu); |
1773 | po->rollover = NULL; | 1773 | po->rollover = NULL; |
1774 | } | 1774 | } |
1775 | mutex_unlock(&fanout_mutex); | 1775 | mutex_unlock(&fanout_mutex); |
@@ -1796,8 +1796,10 @@ static struct packet_fanout *fanout_release(struct sock *sk) | |||
1796 | else | 1796 | else |
1797 | f = NULL; | 1797 | f = NULL; |
1798 | 1798 | ||
1799 | if (po->rollover) | 1799 | if (po->rollover) { |
1800 | kfree_rcu(po->rollover, rcu); | 1800 | kfree_rcu(po->rollover, rcu); |
1801 | po->rollover = NULL; | ||
1802 | } | ||
1801 | } | 1803 | } |
1802 | mutex_unlock(&fanout_mutex); | 1804 | mutex_unlock(&fanout_mutex); |
1803 | 1805 | ||
@@ -3851,6 +3853,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3851 | void *data = &val; | 3853 | void *data = &val; |
3852 | union tpacket_stats_u st; | 3854 | union tpacket_stats_u st; |
3853 | struct tpacket_rollover_stats rstats; | 3855 | struct tpacket_rollover_stats rstats; |
3856 | struct packet_rollover *rollover; | ||
3854 | 3857 | ||
3855 | if (level != SOL_PACKET) | 3858 | if (level != SOL_PACKET) |
3856 | return -ENOPROTOOPT; | 3859 | return -ENOPROTOOPT; |
@@ -3929,13 +3932,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3929 | 0); | 3932 | 0); |
3930 | break; | 3933 | break; |
3931 | case PACKET_ROLLOVER_STATS: | 3934 | case PACKET_ROLLOVER_STATS: |
3932 | if (!po->rollover) | 3935 | rcu_read_lock(); |
3936 | rollover = rcu_dereference(po->rollover); | ||
3937 | if (rollover) { | ||
3938 | rstats.tp_all = atomic_long_read(&rollover->num); | ||
3939 | rstats.tp_huge = atomic_long_read(&rollover->num_huge); | ||
3940 | rstats.tp_failed = atomic_long_read(&rollover->num_failed); | ||
3941 | data = &rstats; | ||
3942 | lv = sizeof(rstats); | ||
3943 | } | ||
3944 | rcu_read_unlock(); | ||
3945 | if (!rollover) | ||
3933 | return -EINVAL; | 3946 | return -EINVAL; |
3934 | rstats.tp_all = atomic_long_read(&po->rollover->num); | ||
3935 | rstats.tp_huge = atomic_long_read(&po->rollover->num_huge); | ||
3936 | rstats.tp_failed = atomic_long_read(&po->rollover->num_failed); | ||
3937 | data = &rstats; | ||
3938 | lv = sizeof(rstats); | ||
3939 | break; | 3947 | break; |
3940 | case PACKET_TX_HAS_OFF: | 3948 | case PACKET_TX_HAS_OFF: |
3941 | val = po->tp_tx_has_off; | 3949 | val = po->tp_tx_has_off; |