inet: drop prev pointer handling in request sock
When request sock are put in ehash table, the whole notion of having a previous request to update dl_next is pointless. Also, following patch will get rid of big purge timer, so we want to delete a request sock without holding listener lock. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
a998f712f7
commit
52452c5425
@@ -480,18 +480,17 @@ static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
|
||||
#endif
|
||||
|
||||
struct request_sock *inet_csk_search_req(const struct sock *sk,
|
||||
struct request_sock ***prevp,
|
||||
const __be16 rport, const __be32 raddr,
|
||||
const __be32 laddr)
|
||||
{
|
||||
const struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
|
||||
struct request_sock *req, **prev;
|
||||
struct request_sock *req;
|
||||
|
||||
for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
|
||||
lopt->nr_table_entries)];
|
||||
(req = *prev) != NULL;
|
||||
prev = &req->dl_next) {
|
||||
for (req = lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
|
||||
lopt->nr_table_entries)];
|
||||
req != NULL;
|
||||
req = req->dl_next) {
|
||||
const struct inet_request_sock *ireq = inet_rsk(req);
|
||||
|
||||
if (ireq->ir_rmt_port == rport &&
|
||||
@@ -499,7 +498,6 @@ struct request_sock *inet_csk_search_req(const struct sock *sk,
|
||||
ireq->ir_loc_addr == laddr &&
|
||||
AF_INET_FAMILY(req->rsk_ops->family)) {
|
||||
WARN_ON(req->sk);
|
||||
*prevp = prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -610,7 +608,10 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
|
||||
i = lopt->clock_hand;
|
||||
|
||||
do {
|
||||
reqp=&lopt->syn_table[i];
|
||||
reqp = &lopt->syn_table[i];
|
||||
if (!*reqp)
|
||||
goto next_bucket;
|
||||
write_lock(&queue->syn_wait_lock);
|
||||
while ((req = *reqp) != NULL) {
|
||||
if (time_after_eq(now, req->expires)) {
|
||||
int expire = 0, resend = 0;
|
||||
@@ -635,14 +636,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
|
||||
}
|
||||
|
||||
/* Drop this request */
|
||||
inet_csk_reqsk_queue_unlink(parent, req, reqp);
|
||||
*reqp = req->dl_next;
|
||||
reqsk_queue_removed(queue, req);
|
||||
reqsk_put(req);
|
||||
continue;
|
||||
}
|
||||
reqp = &req->dl_next;
|
||||
}
|
||||
|
||||
write_unlock(&queue->syn_wait_lock);
|
||||
next_bucket:
|
||||
i = (i + 1) & (lopt->nr_table_entries - 1);
|
||||
|
||||
} while (--budget > 0);
|
||||
|
@@ -5694,7 +5694,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
||||
WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
|
||||
sk->sk_state != TCP_FIN_WAIT1);
|
||||
|
||||
if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
|
||||
if (tcp_check_req(sk, skb, req, true) == NULL)
|
||||
goto discard;
|
||||
}
|
||||
|
||||
|
@@ -458,12 +458,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
|
||||
}
|
||||
|
||||
switch (sk->sk_state) {
|
||||
struct request_sock *req, **prev;
|
||||
struct request_sock *req;
|
||||
case TCP_LISTEN:
|
||||
if (sock_owned_by_user(sk))
|
||||
goto out;
|
||||
|
||||
req = inet_csk_search_req(sk, &prev, th->dest,
|
||||
req = inet_csk_search_req(sk, th->dest,
|
||||
iph->daddr, iph->saddr);
|
||||
if (!req)
|
||||
goto out;
|
||||
@@ -484,7 +484,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
|
||||
* created socket, and POSIX does not want network
|
||||
* errors returned from accept().
|
||||
*/
|
||||
inet_csk_reqsk_queue_drop(sk, req, prev);
|
||||
inet_csk_reqsk_queue_drop(sk, req);
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
|
||||
goto out;
|
||||
|
||||
@@ -1392,15 +1392,14 @@ EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
|
||||
|
||||
static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct tcphdr *th = tcp_hdr(skb);
|
||||
const struct tcphdr *th = tcp_hdr(skb);
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct request_sock *req;
|
||||
struct sock *nsk;
|
||||
struct request_sock **prev;
|
||||
/* Find possible connection requests. */
|
||||
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
|
||||
iph->saddr, iph->daddr);
|
||||
|
||||
req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
|
||||
if (req)
|
||||
return tcp_check_req(sk, skb, req, prev, false);
|
||||
return tcp_check_req(sk, skb, req, false);
|
||||
|
||||
nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
|
||||
th->source, iph->daddr, th->dest, inet_iif(skb));
|
||||
|
@@ -572,7 +572,6 @@ EXPORT_SYMBOL(tcp_create_openreq_child);
|
||||
|
||||
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req,
|
||||
struct request_sock **prev,
|
||||
bool fastopen)
|
||||
{
|
||||
struct tcp_options_received tmp_opt;
|
||||
@@ -766,7 +765,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
if (child == NULL)
|
||||
goto listen_overflow;
|
||||
|
||||
inet_csk_reqsk_queue_unlink(sk, req, prev);
|
||||
inet_csk_reqsk_queue_unlink(sk, req);
|
||||
inet_csk_reqsk_queue_removed(sk, req);
|
||||
|
||||
inet_csk_reqsk_queue_add(sk, req, child);
|
||||
@@ -791,7 +790,7 @@ embryonic_reset:
|
||||
tcp_reset(sk);
|
||||
}
|
||||
if (!fastopen) {
|
||||
inet_csk_reqsk_queue_drop(sk, req, prev);
|
||||
inet_csk_reqsk_queue_drop(sk, req);
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
|
||||
}
|
||||
return NULL;
|
||||
|
Reference in New Issue
Block a user