diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f88653138621..1d723de18686 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -255,11 +255,14 @@ | |||
255 | #include <linux/init.h> | 255 | #include <linux/init.h> |
256 | #include <linux/fs.h> | 256 | #include <linux/fs.h> |
257 | #include <linux/skbuff.h> | 257 | #include <linux/skbuff.h> |
258 | #include <linux/scatterlist.h> | ||
258 | #include <linux/splice.h> | 259 | #include <linux/splice.h> |
259 | #include <linux/net.h> | 260 | #include <linux/net.h> |
260 | #include <linux/socket.h> | 261 | #include <linux/socket.h> |
261 | #include <linux/random.h> | 262 | #include <linux/random.h> |
262 | #include <linux/bootmem.h> | 263 | #include <linux/bootmem.h> |
264 | #include <linux/highmem.h> | ||
265 | #include <linux/swap.h> | ||
263 | #include <linux/cache.h> | 266 | #include <linux/cache.h> |
264 | #include <linux/err.h> | 267 | #include <linux/err.h> |
265 | #include <linux/crypto.h> | 268 | #include <linux/crypto.h> |
@@ -1206,7 +1209,8 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1206 | return -ENOTCONN; | 1209 | return -ENOTCONN; |
1207 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | 1210 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { |
1208 | if (offset < skb->len) { | 1211 | if (offset < skb->len) { |
1209 | size_t used, len; | 1212 | int used; |
1213 | size_t len; | ||
1210 | 1214 | ||
1211 | len = skb->len - offset; | 1215 | len = skb->len - offset; |
1212 | /* Stop reading if we hit a patch of urgent data */ | 1216 | /* Stop reading if we hit a patch of urgent data */ |
@@ -1227,7 +1231,14 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1227 | copied += used; | 1231 | copied += used; |
1228 | offset += used; | 1232 | offset += used; |
1229 | } | 1233 | } |
1230 | if (offset != skb->len) | 1234 | /* |
1235 | * If recv_actor drops the lock (e.g. TCP splice | ||
1236 | * receive) the skb pointer might be invalid when | ||
1237 | * getting here: tcp_collapse might have deleted it | ||
1238 | * while aggregating skbs from the socket queue. | ||
1239 | */ | ||
1240 | skb = tcp_recv_skb(sk, seq-1, &offset); | ||
1241 | if (!skb || (offset+1 != skb->len)) | ||
1231 | break; | 1242 | break; |
1232 | } | 1243 | } |
1233 | if (tcp_hdr(skb)->fin) { | 1244 | if (tcp_hdr(skb)->fin) { |
@@ -2105,12 +2116,15 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2105 | break; | 2116 | break; |
2106 | 2117 | ||
2107 | case TCP_DEFER_ACCEPT: | 2118 | case TCP_DEFER_ACCEPT: |
2108 | if (val < 0) { | 2119 | icsk->icsk_accept_queue.rskq_defer_accept = 0; |
2109 | err = -EINVAL; | 2120 | if (val > 0) { |
2110 | } else { | 2121 | /* Translate value in seconds to number of |
2111 | if (val > MAX_TCP_ACCEPT_DEFERRED) | 2122 | * retransmits */ |
2112 | val = MAX_TCP_ACCEPT_DEFERRED; | 2123 | while (icsk->icsk_accept_queue.rskq_defer_accept < 32 && |
2113 | icsk->icsk_accept_queue.rskq_defer_accept = val; | 2124 | val > ((TCP_TIMEOUT_INIT / HZ) << |
2125 | icsk->icsk_accept_queue.rskq_defer_accept)) | ||
2126 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
2127 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
2114 | } | 2128 | } |
2115 | break; | 2129 | break; |
2116 | 2130 | ||
@@ -2292,7 +2306,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2292 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; | 2306 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; |
2293 | break; | 2307 | break; |
2294 | case TCP_DEFER_ACCEPT: | 2308 | case TCP_DEFER_ACCEPT: |
2295 | val = icsk->icsk_accept_queue.rskq_defer_accept; | 2309 | val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : |
2310 | ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); | ||
2296 | break; | 2311 | break; |
2297 | case TCP_WINDOW_CLAMP: | 2312 | case TCP_WINDOW_CLAMP: |
2298 | val = tp->window_clamp; | 2313 | val = tp->window_clamp; |
@@ -2609,7 +2624,7 @@ __setup("thash_entries=", set_thash_entries); | |||
2609 | void __init tcp_init(void) | 2624 | void __init tcp_init(void) |
2610 | { | 2625 | { |
2611 | struct sk_buff *skb = NULL; | 2626 | struct sk_buff *skb = NULL; |
2612 | unsigned long limit; | 2627 | unsigned long nr_pages, limit; |
2613 | int order, i, max_share; | 2628 | int order, i, max_share; |
2614 | 2629 | ||
2615 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); | 2630 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); |
@@ -2678,8 +2693,9 @@ void __init tcp_init(void) | |||
2678 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of | 2693 | * is up to 1/2 at 256 MB, decreasing toward zero with the amount of |
2679 | * memory, with a floor of 128 pages. | 2694 | * memory, with a floor of 128 pages. |
2680 | */ | 2695 | */ |
2681 | limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); | 2696 | nr_pages = totalram_pages - totalhigh_pages; |
2682 | limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | 2697 | limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); |
2698 | limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); | ||
2683 | limit = max(limit, 128UL); | 2699 | limit = max(limit, 128UL); |
2684 | sysctl_tcp_mem[0] = limit / 4 * 3; | 2700 | sysctl_tcp_mem[0] = limit / 4 * 3; |
2685 | sysctl_tcp_mem[1] = limit; | 2701 | sysctl_tcp_mem[1] = limit; |