diff options
Diffstat (limited to 'net/ipv4/tcp_fastopen.c')
| -rw-r--r-- | net/ipv4/tcp_fastopen.c | 20 | 
1 files changed, 8 insertions, 12 deletions
| diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index ea82fd492c1b..e3d87aca6be8 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
| @@ -141,7 +141,7 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 141 | req->sk = NULL; | 141 | req->sk = NULL; | 
| 142 | 142 | ||
| 143 | child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); | 143 | child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); | 
| 144 | if (child == NULL) | 144 | if (!child) | 
| 145 | return false; | 145 | return false; | 
| 146 | 146 | ||
| 147 | spin_lock(&queue->fastopenq->lock); | 147 | spin_lock(&queue->fastopenq->lock); | 
| @@ -155,12 +155,7 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 155 | tp = tcp_sk(child); | 155 | tp = tcp_sk(child); | 
| 156 | 156 | ||
| 157 | tp->fastopen_rsk = req; | 157 | tp->fastopen_rsk = req; | 
| 158 | /* Do a hold on the listner sk so that if the listener is being | 158 | tcp_rsk(req)->tfo_listener = true; | 
| 159 | * closed, the child that has been accepted can live on and still | ||
| 160 | * access listen_lock. | ||
| 161 | */ | ||
| 162 | sock_hold(sk); | ||
| 163 | tcp_rsk(req)->listener = sk; | ||
| 164 | 159 | ||
| 165 | /* RFC1323: The window in SYN & SYN/ACK segments is never | 160 | /* RFC1323: The window in SYN & SYN/ACK segments is never | 
| 166 | * scaled. So correct it appropriately. | 161 | * scaled. So correct it appropriately. | 
| @@ -174,6 +169,7 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 174 | inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS, | 169 | inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS, | 
| 175 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); | 170 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); | 
| 176 | 171 | ||
| 172 | atomic_set(&req->rsk_refcnt, 1); | ||
| 177 | /* Add the child socket directly into the accept queue */ | 173 | /* Add the child socket directly into the accept queue */ | 
| 178 | inet_csk_reqsk_queue_add(sk, req, child); | 174 | inet_csk_reqsk_queue_add(sk, req, child); | 
| 179 | 175 | ||
| @@ -218,10 +214,9 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
| 218 | sk->sk_data_ready(sk); | 214 | sk->sk_data_ready(sk); | 
| 219 | bh_unlock_sock(child); | 215 | bh_unlock_sock(child); | 
| 220 | sock_put(child); | 216 | sock_put(child); | 
| 221 | WARN_ON(req->sk == NULL); | 217 | WARN_ON(!req->sk); | 
| 222 | return true; | 218 | return true; | 
| 223 | } | 219 | } | 
| 224 | EXPORT_SYMBOL(tcp_fastopen_create_child); | ||
| 225 | 220 | ||
| 226 | static bool tcp_fastopen_queue_check(struct sock *sk) | 221 | static bool tcp_fastopen_queue_check(struct sock *sk) | 
| 227 | { | 222 | { | 
| @@ -238,14 +233,14 @@ static bool tcp_fastopen_queue_check(struct sock *sk) | |||
| 238 | * temporarily vs a server not supporting Fast Open at all. | 233 | * temporarily vs a server not supporting Fast Open at all. | 
| 239 | */ | 234 | */ | 
| 240 | fastopenq = inet_csk(sk)->icsk_accept_queue.fastopenq; | 235 | fastopenq = inet_csk(sk)->icsk_accept_queue.fastopenq; | 
| 241 | if (fastopenq == NULL || fastopenq->max_qlen == 0) | 236 | if (!fastopenq || fastopenq->max_qlen == 0) | 
| 242 | return false; | 237 | return false; | 
| 243 | 238 | ||
| 244 | if (fastopenq->qlen >= fastopenq->max_qlen) { | 239 | if (fastopenq->qlen >= fastopenq->max_qlen) { | 
| 245 | struct request_sock *req1; | 240 | struct request_sock *req1; | 
| 246 | spin_lock(&fastopenq->lock); | 241 | spin_lock(&fastopenq->lock); | 
| 247 | req1 = fastopenq->rskq_rst_head; | 242 | req1 = fastopenq->rskq_rst_head; | 
| 248 | if ((req1 == NULL) || time_after(req1->expires, jiffies)) { | 243 | if (!req1 || time_after(req1->rsk_timer.expires, jiffies)) { | 
| 249 | spin_unlock(&fastopenq->lock); | 244 | spin_unlock(&fastopenq->lock); | 
| 250 | NET_INC_STATS_BH(sock_net(sk), | 245 | NET_INC_STATS_BH(sock_net(sk), | 
| 251 | LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); | 246 | LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); | 
| @@ -254,7 +249,7 @@ static bool tcp_fastopen_queue_check(struct sock *sk) | |||
| 254 | fastopenq->rskq_rst_head = req1->dl_next; | 249 | fastopenq->rskq_rst_head = req1->dl_next; | 
| 255 | fastopenq->qlen--; | 250 | fastopenq->qlen--; | 
| 256 | spin_unlock(&fastopenq->lock); | 251 | spin_unlock(&fastopenq->lock); | 
| 257 | reqsk_free(req1); | 252 | reqsk_put(req1); | 
| 258 | } | 253 | } | 
| 259 | return true; | 254 | return true; | 
| 260 | } | 255 | } | 
| @@ -308,6 +303,7 @@ fastopen: | |||
| 308 | } else if (foc->len > 0) /* Client presents an invalid cookie */ | 303 | } else if (foc->len > 0) /* Client presents an invalid cookie */ | 
| 309 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); | 304 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); | 
| 310 | 305 | ||
| 306 | valid_foc.exp = foc->exp; | ||
| 311 | *foc = valid_foc; | 307 | *foc = valid_foc; | 
| 312 | return false; | 308 | return false; | 
| 313 | } | 309 | } | 
