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 3f5caa3fbd06..4f4fa323171d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1767,7 +1767,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
1767 | 1767 | ||
1768 | out: | 1768 | out: |
1769 | if (err && rollover) { | 1769 | if (err && rollover) { |
1770 | kfree(rollover); | 1770 | kfree_rcu(rollover, rcu); |
1771 | po->rollover = NULL; | 1771 | po->rollover = NULL; |
1772 | } | 1772 | } |
1773 | mutex_unlock(&fanout_mutex); | 1773 | mutex_unlock(&fanout_mutex); |
@@ -1794,8 +1794,10 @@ static struct packet_fanout *fanout_release(struct sock *sk) | |||
1794 | else | 1794 | else |
1795 | f = NULL; | 1795 | f = NULL; |
1796 | 1796 | ||
1797 | if (po->rollover) | 1797 | if (po->rollover) { |
1798 | kfree_rcu(po->rollover, rcu); | 1798 | kfree_rcu(po->rollover, rcu); |
1799 | po->rollover = NULL; | ||
1800 | } | ||
1799 | } | 1801 | } |
1800 | mutex_unlock(&fanout_mutex); | 1802 | mutex_unlock(&fanout_mutex); |
1801 | 1803 | ||
@@ -3849,6 +3851,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3849 | void *data = &val; | 3851 | void *data = &val; |
3850 | union tpacket_stats_u st; | 3852 | union tpacket_stats_u st; |
3851 | struct tpacket_rollover_stats rstats; | 3853 | struct tpacket_rollover_stats rstats; |
3854 | struct packet_rollover *rollover; | ||
3852 | 3855 | ||
3853 | if (level != SOL_PACKET) | 3856 | if (level != SOL_PACKET) |
3854 | return -ENOPROTOOPT; | 3857 | return -ENOPROTOOPT; |
@@ -3927,13 +3930,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, | |||
3927 | 0); | 3930 | 0); |
3928 | break; | 3931 | break; |
3929 | case PACKET_ROLLOVER_STATS: | 3932 | case PACKET_ROLLOVER_STATS: |
3930 | if (!po->rollover) | 3933 | rcu_read_lock(); |
3934 | rollover = rcu_dereference(po->rollover); | ||
3935 | if (rollover) { | ||
3936 | rstats.tp_all = atomic_long_read(&rollover->num); | ||
3937 | rstats.tp_huge = atomic_long_read(&rollover->num_huge); | ||
3938 | rstats.tp_failed = atomic_long_read(&rollover->num_failed); | ||
3939 | data = &rstats; | ||
3940 | lv = sizeof(rstats); | ||
3941 | } | ||
3942 | rcu_read_unlock(); | ||
3943 | if (!rollover) | ||
3931 | return -EINVAL; | 3944 | return -EINVAL; |
3932 | rstats.tp_all = atomic_long_read(&po->rollover->num); | ||
3933 | rstats.tp_huge = atomic_long_read(&po->rollover->num_huge); | ||
3934 | rstats.tp_failed = atomic_long_read(&po->rollover->num_failed); | ||
3935 | data = &rstats; | ||
3936 | lv = sizeof(rstats); | ||
3937 | break; | 3945 | break; |
3938 | case PACKET_TX_HAS_OFF: | 3946 | case PACKET_TX_HAS_OFF: |
3939 | val = po->tp_tx_has_off; | 3947 | val = po->tp_tx_has_off; |