diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 18e3a12eb1b2..46efa03d2b11 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -252,6 +252,7 @@ | |||
252 | #include <linux/types.h> | 252 | #include <linux/types.h> |
253 | #include <linux/fcntl.h> | 253 | #include <linux/fcntl.h> |
254 | #include <linux/poll.h> | 254 | #include <linux/poll.h> |
255 | #include <linux/inet_diag.h> | ||
255 | #include <linux/init.h> | 256 | #include <linux/init.h> |
256 | #include <linux/fs.h> | 257 | #include <linux/fs.h> |
257 | #include <linux/skbuff.h> | 258 | #include <linux/skbuff.h> |
@@ -520,8 +521,10 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
520 | 521 | ||
521 | /* Race breaker. If space is freed after | 522 | /* Race breaker. If space is freed after |
522 | * wspace test but before the flags are set, | 523 | * wspace test but before the flags are set, |
523 | * IO signal will be lost. | 524 | * IO signal will be lost. Memory barrier |
525 | * pairs with the input side. | ||
524 | */ | 526 | */ |
527 | smp_mb__after_atomic(); | ||
525 | if (sk_stream_is_writeable(sk)) | 528 | if (sk_stream_is_writeable(sk)) |
526 | mask |= POLLOUT | POLLWRNORM; | 529 | mask |= POLLOUT | POLLWRNORM; |
527 | } | 530 | } |
@@ -2590,11 +2593,12 @@ EXPORT_SYMBOL(compat_tcp_setsockopt); | |||
2590 | #endif | 2593 | #endif |
2591 | 2594 | ||
2592 | /* Return information about state of tcp endpoint in API format. */ | 2595 | /* Return information about state of tcp endpoint in API format. */ |
2593 | void tcp_get_info(const struct sock *sk, struct tcp_info *info) | 2596 | void tcp_get_info(struct sock *sk, struct tcp_info *info) |
2594 | { | 2597 | { |
2595 | const struct tcp_sock *tp = tcp_sk(sk); | 2598 | const struct tcp_sock *tp = tcp_sk(sk); |
2596 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2599 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2597 | u32 now = tcp_time_stamp; | 2600 | u32 now = tcp_time_stamp; |
2601 | u32 rate; | ||
2598 | 2602 | ||
2599 | memset(info, 0, sizeof(*info)); | 2603 | memset(info, 0, sizeof(*info)); |
2600 | 2604 | ||
@@ -2655,10 +2659,16 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
2655 | 2659 | ||
2656 | info->tcpi_total_retrans = tp->total_retrans; | 2660 | info->tcpi_total_retrans = tp->total_retrans; |
2657 | 2661 | ||
2658 | info->tcpi_pacing_rate = sk->sk_pacing_rate != ~0U ? | 2662 | rate = READ_ONCE(sk->sk_pacing_rate); |
2659 | sk->sk_pacing_rate : ~0ULL; | 2663 | info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL; |
2660 | info->tcpi_max_pacing_rate = sk->sk_max_pacing_rate != ~0U ? | 2664 | |
2661 | sk->sk_max_pacing_rate : ~0ULL; | 2665 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
2666 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | ||
2667 | |||
2668 | spin_lock_bh(&sk->sk_lock.slock); | ||
2669 | info->tcpi_bytes_acked = tp->bytes_acked; | ||
2670 | info->tcpi_bytes_received = tp->bytes_received; | ||
2671 | spin_unlock_bh(&sk->sk_lock.slock); | ||
2662 | } | 2672 | } |
2663 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2673 | EXPORT_SYMBOL_GPL(tcp_get_info); |
2664 | 2674 | ||
@@ -2730,6 +2740,26 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2730 | return -EFAULT; | 2740 | return -EFAULT; |
2731 | return 0; | 2741 | return 0; |
2732 | } | 2742 | } |
2743 | case TCP_CC_INFO: { | ||
2744 | const struct tcp_congestion_ops *ca_ops; | ||
2745 | union tcp_cc_info info; | ||
2746 | size_t sz = 0; | ||
2747 | int attr; | ||
2748 | |||
2749 | if (get_user(len, optlen)) | ||
2750 | return -EFAULT; | ||
2751 | |||
2752 | ca_ops = icsk->icsk_ca_ops; | ||
2753 | if (ca_ops && ca_ops->get_info) | ||
2754 | sz = ca_ops->get_info(sk, ~0U, &attr, &info); | ||
2755 | |||
2756 | len = min_t(unsigned int, len, sz); | ||
2757 | if (put_user(len, optlen)) | ||
2758 | return -EFAULT; | ||
2759 | if (copy_to_user(optval, &info, len)) | ||
2760 | return -EFAULT; | ||
2761 | return 0; | ||
2762 | } | ||
2733 | case TCP_QUICKACK: | 2763 | case TCP_QUICKACK: |
2734 | val = !icsk->icsk_ack.pingpong; | 2764 | val = !icsk->icsk_ack.pingpong; |
2735 | break; | 2765 | break; |