diff options
Diffstat (limited to 'net/ipv4/tcp.c')
| -rw-r--r-- | net/ipv4/tcp.c | 188 |
1 files changed, 123 insertions, 65 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b0a26bb25e2e..65afeaec15b7 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -265,6 +265,7 @@ | |||
| 265 | #include <linux/err.h> | 265 | #include <linux/err.h> |
| 266 | #include <linux/crypto.h> | 266 | #include <linux/crypto.h> |
| 267 | #include <linux/time.h> | 267 | #include <linux/time.h> |
| 268 | #include <linux/slab.h> | ||
| 268 | 269 | ||
| 269 | #include <net/icmp.h> | 270 | #include <net/icmp.h> |
| 270 | #include <net/tcp.h> | 271 | #include <net/tcp.h> |
| @@ -377,7 +378,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 377 | struct sock *sk = sock->sk; | 378 | struct sock *sk = sock->sk; |
| 378 | struct tcp_sock *tp = tcp_sk(sk); | 379 | struct tcp_sock *tp = tcp_sk(sk); |
| 379 | 380 | ||
| 380 | sock_poll_wait(file, sk->sk_sleep, wait); | 381 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 381 | if (sk->sk_state == TCP_LISTEN) | 382 | if (sk->sk_state == TCP_LISTEN) |
| 382 | return inet_csk_listen_poll(sk); | 383 | return inet_csk_listen_poll(sk); |
| 383 | 384 | ||
| @@ -429,7 +430,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 429 | if (tp->urg_seq == tp->copied_seq && | 430 | if (tp->urg_seq == tp->copied_seq && |
| 430 | !sock_flag(sk, SOCK_URGINLINE) && | 431 | !sock_flag(sk, SOCK_URGINLINE) && |
| 431 | tp->urg_data) | 432 | tp->urg_data) |
| 432 | target--; | 433 | target++; |
| 433 | 434 | ||
| 434 | /* Potential race condition. If read of tp below will | 435 | /* Potential race condition. If read of tp below will |
| 435 | * escape above sk->sk_state, we can be illegally awaken | 436 | * escape above sk->sk_state, we can be illegally awaken |
| @@ -536,8 +537,7 @@ static inline void skb_entail(struct sock *sk, struct sk_buff *skb) | |||
| 536 | tp->nonagle &= ~TCP_NAGLE_PUSH; | 537 | tp->nonagle &= ~TCP_NAGLE_PUSH; |
| 537 | } | 538 | } |
| 538 | 539 | ||
| 539 | static inline void tcp_mark_urg(struct tcp_sock *tp, int flags, | 540 | static inline void tcp_mark_urg(struct tcp_sock *tp, int flags) |
| 540 | struct sk_buff *skb) | ||
| 541 | { | 541 | { |
| 542 | if (flags & MSG_OOB) | 542 | if (flags & MSG_OOB) |
| 543 | tp->snd_up = tp->write_seq; | 543 | tp->snd_up = tp->write_seq; |
| @@ -546,13 +546,13 @@ static inline void tcp_mark_urg(struct tcp_sock *tp, int flags, | |||
| 546 | static inline void tcp_push(struct sock *sk, int flags, int mss_now, | 546 | static inline void tcp_push(struct sock *sk, int flags, int mss_now, |
| 547 | int nonagle) | 547 | int nonagle) |
| 548 | { | 548 | { |
| 549 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 550 | |||
| 551 | if (tcp_send_head(sk)) { | 549 | if (tcp_send_head(sk)) { |
| 552 | struct sk_buff *skb = tcp_write_queue_tail(sk); | 550 | struct tcp_sock *tp = tcp_sk(sk); |
| 551 | |||
| 553 | if (!(flags & MSG_MORE) || forced_push(tp)) | 552 | if (!(flags & MSG_MORE) || forced_push(tp)) |
| 554 | tcp_mark_push(tp, skb); | 553 | tcp_mark_push(tp, tcp_write_queue_tail(sk)); |
| 555 | tcp_mark_urg(tp, flags, skb); | 554 | |
| 555 | tcp_mark_urg(tp, flags); | ||
| 556 | __tcp_push_pending_frames(sk, mss_now, | 556 | __tcp_push_pending_frames(sk, mss_now, |
| 557 | (flags & MSG_MORE) ? TCP_NAGLE_CORK : nonagle); | 557 | (flags & MSG_MORE) ? TCP_NAGLE_CORK : nonagle); |
| 558 | } | 558 | } |
| @@ -608,6 +608,7 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, | |||
| 608 | ssize_t spliced; | 608 | ssize_t spliced; |
| 609 | int ret; | 609 | int ret; |
| 610 | 610 | ||
| 611 | sock_rps_record_flow(sk); | ||
| 611 | /* | 612 | /* |
| 612 | * We can't seek on a socket input | 613 | * We can't seek on a socket input |
| 613 | */ | 614 | */ |
| @@ -877,12 +878,12 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, | |||
| 877 | #define TCP_PAGE(sk) (sk->sk_sndmsg_page) | 878 | #define TCP_PAGE(sk) (sk->sk_sndmsg_page) |
| 878 | #define TCP_OFF(sk) (sk->sk_sndmsg_off) | 879 | #define TCP_OFF(sk) (sk->sk_sndmsg_off) |
| 879 | 880 | ||
| 880 | static inline int select_size(struct sock *sk) | 881 | static inline int select_size(struct sock *sk, int sg) |
| 881 | { | 882 | { |
| 882 | struct tcp_sock *tp = tcp_sk(sk); | 883 | struct tcp_sock *tp = tcp_sk(sk); |
| 883 | int tmp = tp->mss_cache; | 884 | int tmp = tp->mss_cache; |
| 884 | 885 | ||
| 885 | if (sk->sk_route_caps & NETIF_F_SG) { | 886 | if (sg) { |
| 886 | if (sk_can_gso(sk)) | 887 | if (sk_can_gso(sk)) |
| 887 | tmp = 0; | 888 | tmp = 0; |
| 888 | else { | 889 | else { |
| @@ -906,7 +907,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 906 | struct sk_buff *skb; | 907 | struct sk_buff *skb; |
| 907 | int iovlen, flags; | 908 | int iovlen, flags; |
| 908 | int mss_now, size_goal; | 909 | int mss_now, size_goal; |
| 909 | int err, copied; | 910 | int sg, err, copied; |
| 910 | long timeo; | 911 | long timeo; |
| 911 | 912 | ||
| 912 | lock_sock(sk); | 913 | lock_sock(sk); |
| @@ -934,6 +935,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 934 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 935 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
| 935 | goto out_err; | 936 | goto out_err; |
| 936 | 937 | ||
| 938 | sg = sk->sk_route_caps & NETIF_F_SG; | ||
| 939 | |||
| 937 | while (--iovlen >= 0) { | 940 | while (--iovlen >= 0) { |
| 938 | int seglen = iov->iov_len; | 941 | int seglen = iov->iov_len; |
| 939 | unsigned char __user *from = iov->iov_base; | 942 | unsigned char __user *from = iov->iov_base; |
| @@ -959,8 +962,9 @@ new_segment: | |||
| 959 | if (!sk_stream_memory_free(sk)) | 962 | if (!sk_stream_memory_free(sk)) |
| 960 | goto wait_for_sndbuf; | 963 | goto wait_for_sndbuf; |
| 961 | 964 | ||
| 962 | skb = sk_stream_alloc_skb(sk, select_size(sk), | 965 | skb = sk_stream_alloc_skb(sk, |
| 963 | sk->sk_allocation); | 966 | select_size(sk, sg), |
| 967 | sk->sk_allocation); | ||
| 964 | if (!skb) | 968 | if (!skb) |
| 965 | goto wait_for_memory; | 969 | goto wait_for_memory; |
| 966 | 970 | ||
| @@ -997,9 +1001,7 @@ new_segment: | |||
| 997 | /* We can extend the last page | 1001 | /* We can extend the last page |
| 998 | * fragment. */ | 1002 | * fragment. */ |
| 999 | merge = 1; | 1003 | merge = 1; |
| 1000 | } else if (i == MAX_SKB_FRAGS || | 1004 | } else if (i == MAX_SKB_FRAGS || !sg) { |
| 1001 | (!i && | ||
| 1002 | !(sk->sk_route_caps & NETIF_F_SG))) { | ||
| 1003 | /* Need to add new fragment and cannot | 1005 | /* Need to add new fragment and cannot |
| 1004 | * do this because interface is non-SG, | 1006 | * do this because interface is non-SG, |
| 1005 | * or because all the page slots are | 1007 | * or because all the page slots are |
| @@ -1254,6 +1256,39 @@ static void tcp_prequeue_process(struct sock *sk) | |||
| 1254 | tp->ucopy.memory = 0; | 1256 | tp->ucopy.memory = 0; |
| 1255 | } | 1257 | } |
| 1256 | 1258 | ||
| 1259 | #ifdef CONFIG_NET_DMA | ||
| 1260 | static void tcp_service_net_dma(struct sock *sk, bool wait) | ||
| 1261 | { | ||
| 1262 | dma_cookie_t done, used; | ||
| 1263 | dma_cookie_t last_issued; | ||
| 1264 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 1265 | |||
| 1266 | if (!tp->ucopy.dma_chan) | ||
| 1267 | return; | ||
| 1268 | |||
| 1269 | last_issued = tp->ucopy.dma_cookie; | ||
| 1270 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
| 1271 | |||
| 1272 | do { | ||
| 1273 | if (dma_async_memcpy_complete(tp->ucopy.dma_chan, | ||
| 1274 | last_issued, &done, | ||
| 1275 | &used) == DMA_SUCCESS) { | ||
| 1276 | /* Safe to free early-copied skbs now */ | ||
| 1277 | __skb_queue_purge(&sk->sk_async_wait_queue); | ||
| 1278 | break; | ||
| 1279 | } else { | ||
| 1280 | struct sk_buff *skb; | ||
| 1281 | while ((skb = skb_peek(&sk->sk_async_wait_queue)) && | ||
| 1282 | (dma_async_is_complete(skb->dma_cookie, done, | ||
| 1283 | used) == DMA_SUCCESS)) { | ||
| 1284 | __skb_dequeue(&sk->sk_async_wait_queue); | ||
| 1285 | kfree_skb(skb); | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | } while (wait); | ||
| 1289 | } | ||
| 1290 | #endif | ||
| 1291 | |||
| 1257 | static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) | 1292 | static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) |
| 1258 | { | 1293 | { |
| 1259 | struct sk_buff *skb; | 1294 | struct sk_buff *skb; |
| @@ -1335,6 +1370,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
| 1335 | sk_eat_skb(sk, skb, 0); | 1370 | sk_eat_skb(sk, skb, 0); |
| 1336 | if (!desc->count) | 1371 | if (!desc->count) |
| 1337 | break; | 1372 | break; |
| 1373 | tp->copied_seq = seq; | ||
| 1338 | } | 1374 | } |
| 1339 | tp->copied_seq = seq; | 1375 | tp->copied_seq = seq; |
| 1340 | 1376 | ||
| @@ -1546,6 +1582,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 1546 | /* __ Set realtime policy in scheduler __ */ | 1582 | /* __ Set realtime policy in scheduler __ */ |
| 1547 | } | 1583 | } |
| 1548 | 1584 | ||
| 1585 | #ifdef CONFIG_NET_DMA | ||
| 1586 | if (tp->ucopy.dma_chan) | ||
| 1587 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
| 1588 | #endif | ||
| 1549 | if (copied >= target) { | 1589 | if (copied >= target) { |
| 1550 | /* Do not sleep, just process backlog. */ | 1590 | /* Do not sleep, just process backlog. */ |
| 1551 | release_sock(sk); | 1591 | release_sock(sk); |
| @@ -1554,6 +1594,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 1554 | sk_wait_data(sk, &timeo); | 1594 | sk_wait_data(sk, &timeo); |
| 1555 | 1595 | ||
| 1556 | #ifdef CONFIG_NET_DMA | 1596 | #ifdef CONFIG_NET_DMA |
| 1597 | tcp_service_net_dma(sk, false); /* Don't block */ | ||
| 1557 | tp->ucopy.wakeup = 0; | 1598 | tp->ucopy.wakeup = 0; |
| 1558 | #endif | 1599 | #endif |
| 1559 | 1600 | ||
| @@ -1633,6 +1674,9 @@ do_prequeue: | |||
| 1633 | copied = -EFAULT; | 1674 | copied = -EFAULT; |
| 1634 | break; | 1675 | break; |
| 1635 | } | 1676 | } |
| 1677 | |||
| 1678 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
| 1679 | |||
| 1636 | if ((offset + used) == skb->len) | 1680 | if ((offset + used) == skb->len) |
| 1637 | copied_early = 1; | 1681 | copied_early = 1; |
| 1638 | 1682 | ||
| @@ -1702,27 +1746,9 @@ skip_copy: | |||
| 1702 | } | 1746 | } |
| 1703 | 1747 | ||
| 1704 | #ifdef CONFIG_NET_DMA | 1748 | #ifdef CONFIG_NET_DMA |
| 1705 | if (tp->ucopy.dma_chan) { | 1749 | tcp_service_net_dma(sk, true); /* Wait for queue to drain */ |
| 1706 | dma_cookie_t done, used; | 1750 | tp->ucopy.dma_chan = NULL; |
| 1707 | |||
| 1708 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
| 1709 | |||
| 1710 | while (dma_async_memcpy_complete(tp->ucopy.dma_chan, | ||
| 1711 | tp->ucopy.dma_cookie, &done, | ||
| 1712 | &used) == DMA_IN_PROGRESS) { | ||
| 1713 | /* do partial cleanup of sk_async_wait_queue */ | ||
| 1714 | while ((skb = skb_peek(&sk->sk_async_wait_queue)) && | ||
| 1715 | (dma_async_is_complete(skb->dma_cookie, done, | ||
| 1716 | used) == DMA_SUCCESS)) { | ||
| 1717 | __skb_dequeue(&sk->sk_async_wait_queue); | ||
| 1718 | kfree_skb(skb); | ||
| 1719 | } | ||
| 1720 | } | ||
| 1721 | 1751 | ||
| 1722 | /* Safe to free early-copied skbs now */ | ||
| 1723 | __skb_queue_purge(&sk->sk_async_wait_queue); | ||
| 1724 | tp->ucopy.dma_chan = NULL; | ||
| 1725 | } | ||
| 1726 | if (tp->ucopy.pinned_list) { | 1752 | if (tp->ucopy.pinned_list) { |
| 1727 | dma_unpin_iovec_pages(tp->ucopy.pinned_list); | 1753 | dma_unpin_iovec_pages(tp->ucopy.pinned_list); |
| 1728 | tp->ucopy.pinned_list = NULL; | 1754 | tp->ucopy.pinned_list = NULL; |
| @@ -2190,7 +2216,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2190 | default: | 2216 | default: |
| 2191 | /* fallthru */ | 2217 | /* fallthru */ |
| 2192 | break; | 2218 | break; |
| 2193 | }; | 2219 | } |
| 2194 | 2220 | ||
| 2195 | if (optlen < sizeof(int)) | 2221 | if (optlen < sizeof(int)) |
| 2196 | return -EINVAL; | 2222 | return -EINVAL; |
| @@ -2229,6 +2255,20 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2229 | } | 2255 | } |
| 2230 | break; | 2256 | break; |
| 2231 | 2257 | ||
| 2258 | case TCP_THIN_LINEAR_TIMEOUTS: | ||
| 2259 | if (val < 0 || val > 1) | ||
| 2260 | err = -EINVAL; | ||
| 2261 | else | ||
| 2262 | tp->thin_lto = val; | ||
| 2263 | break; | ||
| 2264 | |||
| 2265 | case TCP_THIN_DUPACK: | ||
| 2266 | if (val < 0 || val > 1) | ||
| 2267 | err = -EINVAL; | ||
| 2268 | else | ||
| 2269 | tp->thin_dupack = val; | ||
| 2270 | break; | ||
| 2271 | |||
| 2232 | case TCP_CORK: | 2272 | case TCP_CORK: |
| 2233 | /* When set indicates to always queue non-full frames. | 2273 | /* When set indicates to always queue non-full frames. |
| 2234 | * Later the user clears this option and we transmit | 2274 | * Later the user clears this option and we transmit |
| @@ -2259,7 +2299,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2259 | if (sock_flag(sk, SOCK_KEEPOPEN) && | 2299 | if (sock_flag(sk, SOCK_KEEPOPEN) && |
| 2260 | !((1 << sk->sk_state) & | 2300 | !((1 << sk->sk_state) & |
| 2261 | (TCPF_CLOSE | TCPF_LISTEN))) { | 2301 | (TCPF_CLOSE | TCPF_LISTEN))) { |
| 2262 | __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; | 2302 | u32 elapsed = keepalive_time_elapsed(tp); |
| 2263 | if (tp->keepalive_time > elapsed) | 2303 | if (tp->keepalive_time > elapsed) |
| 2264 | elapsed = tp->keepalive_time - elapsed; | 2304 | elapsed = tp->keepalive_time - elapsed; |
| 2265 | else | 2305 | else |
| @@ -2682,7 +2722,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2682 | struct tcphdr *th2; | 2722 | struct tcphdr *th2; |
| 2683 | unsigned int len; | 2723 | unsigned int len; |
| 2684 | unsigned int thlen; | 2724 | unsigned int thlen; |
| 2685 | unsigned int flags; | 2725 | __be32 flags; |
| 2686 | unsigned int mss = 1; | 2726 | unsigned int mss = 1; |
| 2687 | unsigned int hlen; | 2727 | unsigned int hlen; |
| 2688 | unsigned int off; | 2728 | unsigned int off; |
| @@ -2732,10 +2772,10 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2732 | 2772 | ||
| 2733 | found: | 2773 | found: |
| 2734 | flush = NAPI_GRO_CB(p)->flush; | 2774 | flush = NAPI_GRO_CB(p)->flush; |
| 2735 | flush |= flags & TCP_FLAG_CWR; | 2775 | flush |= (__force int)(flags & TCP_FLAG_CWR); |
| 2736 | flush |= (flags ^ tcp_flag_word(th2)) & | 2776 | flush |= (__force int)((flags ^ tcp_flag_word(th2)) & |
| 2737 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); | 2777 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); |
| 2738 | flush |= th->ack_seq ^ th2->ack_seq; | 2778 | flush |= (__force int)(th->ack_seq ^ th2->ack_seq); |
| 2739 | for (i = sizeof(*th); i < thlen; i += 4) | 2779 | for (i = sizeof(*th); i < thlen; i += 4) |
| 2740 | flush |= *(u32 *)((u8 *)th + i) ^ | 2780 | flush |= *(u32 *)((u8 *)th + i) ^ |
| 2741 | *(u32 *)((u8 *)th2 + i); | 2781 | *(u32 *)((u8 *)th2 + i); |
| @@ -2756,8 +2796,9 @@ found: | |||
| 2756 | 2796 | ||
| 2757 | out_check_final: | 2797 | out_check_final: |
| 2758 | flush = len < mss; | 2798 | flush = len < mss; |
| 2759 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2799 | flush |= (__force int)(flags & (TCP_FLAG_URG | TCP_FLAG_PSH | |
| 2760 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2800 | TCP_FLAG_RST | TCP_FLAG_SYN | |
| 2801 | TCP_FLAG_FIN)); | ||
| 2761 | 2802 | ||
| 2762 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) | 2803 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) |
| 2763 | pp = head; | 2804 | pp = head; |
| @@ -2788,10 +2829,10 @@ EXPORT_SYMBOL(tcp_gro_complete); | |||
| 2788 | 2829 | ||
| 2789 | #ifdef CONFIG_TCP_MD5SIG | 2830 | #ifdef CONFIG_TCP_MD5SIG |
| 2790 | static unsigned long tcp_md5sig_users; | 2831 | static unsigned long tcp_md5sig_users; |
| 2791 | static struct tcp_md5sig_pool **tcp_md5sig_pool; | 2832 | static struct tcp_md5sig_pool * __percpu *tcp_md5sig_pool; |
| 2792 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); | 2833 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); |
| 2793 | 2834 | ||
| 2794 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | 2835 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) |
| 2795 | { | 2836 | { |
| 2796 | int cpu; | 2837 | int cpu; |
| 2797 | for_each_possible_cpu(cpu) { | 2838 | for_each_possible_cpu(cpu) { |
| @@ -2800,7 +2841,6 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | |||
| 2800 | if (p->md5_desc.tfm) | 2841 | if (p->md5_desc.tfm) |
| 2801 | crypto_free_hash(p->md5_desc.tfm); | 2842 | crypto_free_hash(p->md5_desc.tfm); |
| 2802 | kfree(p); | 2843 | kfree(p); |
| 2803 | p = NULL; | ||
| 2804 | } | 2844 | } |
| 2805 | } | 2845 | } |
| 2806 | free_percpu(pool); | 2846 | free_percpu(pool); |
| @@ -2808,7 +2848,7 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | |||
| 2808 | 2848 | ||
| 2809 | void tcp_free_md5sig_pool(void) | 2849 | void tcp_free_md5sig_pool(void) |
| 2810 | { | 2850 | { |
| 2811 | struct tcp_md5sig_pool **pool = NULL; | 2851 | struct tcp_md5sig_pool * __percpu *pool = NULL; |
| 2812 | 2852 | ||
| 2813 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2853 | spin_lock_bh(&tcp_md5sig_pool_lock); |
| 2814 | if (--tcp_md5sig_users == 0) { | 2854 | if (--tcp_md5sig_users == 0) { |
| @@ -2822,10 +2862,11 @@ void tcp_free_md5sig_pool(void) | |||
| 2822 | 2862 | ||
| 2823 | EXPORT_SYMBOL(tcp_free_md5sig_pool); | 2863 | EXPORT_SYMBOL(tcp_free_md5sig_pool); |
| 2824 | 2864 | ||
| 2825 | static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(struct sock *sk) | 2865 | static struct tcp_md5sig_pool * __percpu * |
| 2866 | __tcp_alloc_md5sig_pool(struct sock *sk) | ||
| 2826 | { | 2867 | { |
| 2827 | int cpu; | 2868 | int cpu; |
| 2828 | struct tcp_md5sig_pool **pool; | 2869 | struct tcp_md5sig_pool * __percpu *pool; |
| 2829 | 2870 | ||
| 2830 | pool = alloc_percpu(struct tcp_md5sig_pool *); | 2871 | pool = alloc_percpu(struct tcp_md5sig_pool *); |
| 2831 | if (!pool) | 2872 | if (!pool) |
| @@ -2852,9 +2893,9 @@ out_free: | |||
| 2852 | return NULL; | 2893 | return NULL; |
| 2853 | } | 2894 | } |
| 2854 | 2895 | ||
| 2855 | struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *sk) | 2896 | struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *sk) |
| 2856 | { | 2897 | { |
| 2857 | struct tcp_md5sig_pool **pool; | 2898 | struct tcp_md5sig_pool * __percpu *pool; |
| 2858 | int alloc = 0; | 2899 | int alloc = 0; |
| 2859 | 2900 | ||
| 2860 | retry: | 2901 | retry: |
| @@ -2873,7 +2914,9 @@ retry: | |||
| 2873 | 2914 | ||
| 2874 | if (alloc) { | 2915 | if (alloc) { |
| 2875 | /* we cannot hold spinlock here because this may sleep. */ | 2916 | /* we cannot hold spinlock here because this may sleep. */ |
| 2876 | struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(sk); | 2917 | struct tcp_md5sig_pool * __percpu *p; |
| 2918 | |||
| 2919 | p = __tcp_alloc_md5sig_pool(sk); | ||
| 2877 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2920 | spin_lock_bh(&tcp_md5sig_pool_lock); |
| 2878 | if (!p) { | 2921 | if (!p) { |
| 2879 | tcp_md5sig_users--; | 2922 | tcp_md5sig_users--; |
| @@ -2895,25 +2938,40 @@ retry: | |||
| 2895 | 2938 | ||
| 2896 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); | 2939 | EXPORT_SYMBOL(tcp_alloc_md5sig_pool); |
| 2897 | 2940 | ||
| 2898 | struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) | 2941 | |
| 2942 | /** | ||
| 2943 | * tcp_get_md5sig_pool - get md5sig_pool for this user | ||
| 2944 | * | ||
| 2945 | * We use percpu structure, so if we succeed, we exit with preemption | ||
| 2946 | * and BH disabled, to make sure another thread or softirq handling | ||
| 2947 | * wont try to get same context. | ||
| 2948 | */ | ||
| 2949 | struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) | ||
| 2899 | { | 2950 | { |
| 2900 | struct tcp_md5sig_pool **p; | 2951 | struct tcp_md5sig_pool * __percpu *p; |
| 2901 | spin_lock_bh(&tcp_md5sig_pool_lock); | 2952 | |
| 2953 | local_bh_disable(); | ||
| 2954 | |||
| 2955 | spin_lock(&tcp_md5sig_pool_lock); | ||
| 2902 | p = tcp_md5sig_pool; | 2956 | p = tcp_md5sig_pool; |
| 2903 | if (p) | 2957 | if (p) |
| 2904 | tcp_md5sig_users++; | 2958 | tcp_md5sig_users++; |
| 2905 | spin_unlock_bh(&tcp_md5sig_pool_lock); | 2959 | spin_unlock(&tcp_md5sig_pool_lock); |
| 2906 | return (p ? *per_cpu_ptr(p, cpu) : NULL); | ||
| 2907 | } | ||
| 2908 | 2960 | ||
| 2909 | EXPORT_SYMBOL(__tcp_get_md5sig_pool); | 2961 | if (p) |
| 2962 | return *per_cpu_ptr(p, smp_processor_id()); | ||
| 2910 | 2963 | ||
| 2911 | void __tcp_put_md5sig_pool(void) | 2964 | local_bh_enable(); |
| 2965 | return NULL; | ||
| 2966 | } | ||
| 2967 | EXPORT_SYMBOL(tcp_get_md5sig_pool); | ||
| 2968 | |||
| 2969 | void tcp_put_md5sig_pool(void) | ||
| 2912 | { | 2970 | { |
| 2971 | local_bh_enable(); | ||
| 2913 | tcp_free_md5sig_pool(); | 2972 | tcp_free_md5sig_pool(); |
| 2914 | } | 2973 | } |
| 2915 | 2974 | EXPORT_SYMBOL(tcp_put_md5sig_pool); | |
| 2916 | EXPORT_SYMBOL(__tcp_put_md5sig_pool); | ||
| 2917 | 2975 | ||
| 2918 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, | 2976 | int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, |
| 2919 | struct tcphdr *th) | 2977 | struct tcphdr *th) |
