Skip to content

Commit 52452c5

Browse files
edumazetdavem330
authored andcommitted
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>
1 parent a998f71 commit 52452c5

14 files changed

+67
-74
lines changed

include/net/inet6_connection_sock.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, struct flowi6 *fl6,
2929
const struct request_sock *req);
3030

3131
struct request_sock *inet6_csk_search_req(const struct sock *sk,
32-
struct request_sock ***prevp,
3332
const __be16 rport,
3433
const struct in6_addr *raddr,
3534
const struct in6_addr *laddr,

include/net/inet_connection_sock.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
257257
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
258258

259259
struct request_sock *inet_csk_search_req(const struct sock *sk,
260-
struct request_sock ***prevp,
261260
const __be16 rport,
262261
const __be32 raddr,
263262
const __be32 laddr);
@@ -310,17 +309,15 @@ static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
310309
}
311310

312311
static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
313-
struct request_sock *req,
314-
struct request_sock **prev)
312+
struct request_sock *req)
315313
{
316-
reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev);
314+
reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req);
317315
}
318316

319317
static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
320-
struct request_sock *req,
321-
struct request_sock **prev)
318+
struct request_sock *req)
322319
{
323-
inet_csk_reqsk_queue_unlink(sk, req, prev);
320+
inet_csk_reqsk_queue_unlink(sk, req);
324321
inet_csk_reqsk_queue_removed(sk, req);
325322
reqsk_free(req);
326323
}

include/net/request_sock.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
5050
struct request_sock {
5151
struct sock_common __req_common;
5252
#define rsk_refcnt __req_common.skc_refcnt
53+
#define rsk_hash __req_common.skc_hash
5354

5455
struct request_sock *dl_next;
5556
struct sock *rsk_listener;
@@ -216,11 +217,16 @@ static inline int reqsk_queue_empty(struct request_sock_queue *queue)
216217
}
217218

218219
static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
219-
struct request_sock *req,
220-
struct request_sock **prev_req)
220+
struct request_sock *req)
221221
{
222+
struct listen_sock *lopt = queue->listen_opt;
223+
struct request_sock **prev;
224+
222225
write_lock(&queue->syn_wait_lock);
223-
*prev_req = req->dl_next;
226+
prev = &lopt->syn_table[req->rsk_hash];
227+
while (*prev != req)
228+
prev = &(*prev)->dl_next;
229+
*prev = req->dl_next;
224230
write_unlock(&queue->syn_wait_lock);
225231
}
226232

@@ -300,15 +306,16 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
300306
req->num_retrans = 0;
301307
req->num_timeout = 0;
302308
req->sk = NULL;
303-
req->dl_next = lopt->syn_table[hash];
304309

305310
/* before letting lookups find us, make sure all req fields
306311
* are committed to memory and refcnt initialized.
307312
*/
308313
smp_wmb();
309314
atomic_set(&req->rsk_refcnt, 1);
310315

316+
req->rsk_hash = hash;
311317
write_lock(&queue->syn_wait_lock);
318+
req->dl_next = lopt->syn_table[hash];
312319
lopt->syn_table[hash] = req;
313320
write_unlock(&queue->syn_wait_lock);
314321
}

include/net/tcp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,7 @@ enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
406406
struct sk_buff *skb,
407407
const struct tcphdr *th);
408408
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
409-
struct request_sock *req, struct request_sock **prev,
410-
bool fastopen);
409+
struct request_sock *req, bool fastopen);
411410
int tcp_child_process(struct sock *parent, struct sock *child,
412411
struct sk_buff *skb);
413412
void tcp_enter_loss(struct sock *sk);

net/dccp/dccp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
280280
struct request_sock *req,
281281
struct dst_entry *dst);
282282
struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
283-
struct request_sock *req,
284-
struct request_sock **prev);
283+
struct request_sock *req);
285284

286285
int dccp_child_process(struct sock *parent, struct sock *child,
287286
struct sk_buff *skb);

net/dccp/ipv4.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,11 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
288288
}
289289

290290
switch (sk->sk_state) {
291-
struct request_sock *req , **prev;
291+
struct request_sock *req;
292292
case DCCP_LISTEN:
293293
if (sock_owned_by_user(sk))
294294
goto out;
295-
req = inet_csk_search_req(sk, &prev, dh->dccph_dport,
295+
req = inet_csk_search_req(sk, dh->dccph_dport,
296296
iph->daddr, iph->saddr);
297297
if (!req)
298298
goto out;
@@ -314,7 +314,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
314314
* created socket, and POSIX does not want network
315315
* errors returned from accept().
316316
*/
317-
inet_csk_reqsk_queue_drop(sk, req, prev);
317+
inet_csk_reqsk_queue_drop(sk, req);
318318
goto out;
319319

320320
case DCCP_REQUESTING:
@@ -448,13 +448,11 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
448448
const struct dccp_hdr *dh = dccp_hdr(skb);
449449
const struct iphdr *iph = ip_hdr(skb);
450450
struct sock *nsk;
451-
struct request_sock **prev;
452451
/* Find possible connection requests. */
453-
struct request_sock *req = inet_csk_search_req(sk, &prev,
454-
dh->dccph_sport,
452+
struct request_sock *req = inet_csk_search_req(sk, dh->dccph_sport,
455453
iph->saddr, iph->daddr);
456-
if (req != NULL)
457-
return dccp_check_req(sk, skb, req, prev);
454+
if (req)
455+
return dccp_check_req(sk, skb, req);
458456

459457
nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
460458
iph->saddr, dh->dccph_sport,

net/dccp/ipv6.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
149149

150150
/* Might be for an request_sock */
151151
switch (sk->sk_state) {
152-
struct request_sock *req, **prev;
152+
struct request_sock *req;
153153
case DCCP_LISTEN:
154154
if (sock_owned_by_user(sk))
155155
goto out;
156156

157-
req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
157+
req = inet6_csk_search_req(sk, dh->dccph_dport,
158158
&hdr->daddr, &hdr->saddr,
159159
inet6_iif(skb));
160160
if (req == NULL)
@@ -172,7 +172,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
172172
goto out;
173173
}
174174

175-
inet_csk_reqsk_queue_drop(sk, req, prev);
175+
inet_csk_reqsk_queue_drop(sk, req);
176176
goto out;
177177

178178
case DCCP_REQUESTING:
@@ -317,16 +317,13 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
317317
{
318318
const struct dccp_hdr *dh = dccp_hdr(skb);
319319
const struct ipv6hdr *iph = ipv6_hdr(skb);
320+
struct request_sock *req;
320321
struct sock *nsk;
321-
struct request_sock **prev;
322-
/* Find possible connection requests. */
323-
struct request_sock *req = inet6_csk_search_req(sk, &prev,
324-
dh->dccph_sport,
325-
&iph->saddr,
326-
&iph->daddr,
327-
inet6_iif(skb));
322+
323+
req = inet6_csk_search_req(sk, dh->dccph_sport, &iph->saddr,
324+
&iph->daddr, inet6_iif(skb));
328325
if (req != NULL)
329-
return dccp_check_req(sk, skb, req, prev);
326+
return dccp_check_req(sk, skb, req);
330327

331328
nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
332329
&iph->saddr, dh->dccph_sport,

net/dccp/minisocks.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,7 @@ EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
152152
* as an request_sock.
153153
*/
154154
struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
155-
struct request_sock *req,
156-
struct request_sock **prev)
155+
struct request_sock *req)
157156
{
158157
struct sock *child = NULL;
159158
struct dccp_request_sock *dreq = dccp_rsk(req);
@@ -200,7 +199,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
200199
if (child == NULL)
201200
goto listen_overflow;
202201

203-
inet_csk_reqsk_queue_unlink(sk, req, prev);
202+
inet_csk_reqsk_queue_unlink(sk, req);
204203
inet_csk_reqsk_queue_removed(sk, req);
205204
inet_csk_reqsk_queue_add(sk, req, child);
206205
out:
@@ -212,7 +211,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
212211
if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
213212
req->rsk_ops->send_reset(sk, skb);
214213

215-
inet_csk_reqsk_queue_drop(sk, req, prev);
214+
inet_csk_reqsk_queue_drop(sk, req);
216215
goto out;
217216
}
218217

net/ipv4/inet_connection_sock.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -480,26 +480,24 @@ static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
480480
#endif
481481

482482
struct request_sock *inet_csk_search_req(const struct sock *sk,
483-
struct request_sock ***prevp,
484483
const __be16 rport, const __be32 raddr,
485484
const __be32 laddr)
486485
{
487486
const struct inet_connection_sock *icsk = inet_csk(sk);
488487
struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
489-
struct request_sock *req, **prev;
488+
struct request_sock *req;
490489

491-
for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
492-
lopt->nr_table_entries)];
493-
(req = *prev) != NULL;
494-
prev = &req->dl_next) {
490+
for (req = lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
491+
lopt->nr_table_entries)];
492+
req != NULL;
493+
req = req->dl_next) {
495494
const struct inet_request_sock *ireq = inet_rsk(req);
496495

497496
if (ireq->ir_rmt_port == rport &&
498497
ireq->ir_rmt_addr == raddr &&
499498
ireq->ir_loc_addr == laddr &&
500499
AF_INET_FAMILY(req->rsk_ops->family)) {
501500
WARN_ON(req->sk);
502-
*prevp = prev;
503501
break;
504502
}
505503
}
@@ -610,7 +608,10 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
610608
i = lopt->clock_hand;
611609

612610
do {
613-
reqp=&lopt->syn_table[i];
611+
reqp = &lopt->syn_table[i];
612+
if (!*reqp)
613+
goto next_bucket;
614+
write_lock(&queue->syn_wait_lock);
614615
while ((req = *reqp) != NULL) {
615616
if (time_after_eq(now, req->expires)) {
616617
int expire = 0, resend = 0;
@@ -635,14 +636,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
635636
}
636637

637638
/* Drop this request */
638-
inet_csk_reqsk_queue_unlink(parent, req, reqp);
639+
*reqp = req->dl_next;
639640
reqsk_queue_removed(queue, req);
640641
reqsk_put(req);
641642
continue;
642643
}
643644
reqp = &req->dl_next;
644645
}
645-
646+
write_unlock(&queue->syn_wait_lock);
647+
next_bucket:
646648
i = (i + 1) & (lopt->nr_table_entries - 1);
647649

648650
} while (--budget > 0);

net/ipv4/tcp_input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5694,7 +5694,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
56945694
WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
56955695
sk->sk_state != TCP_FIN_WAIT1);
56965696

5697-
if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
5697+
if (tcp_check_req(sk, skb, req, true) == NULL)
56985698
goto discard;
56995699
}
57005700

net/ipv4/tcp_ipv4.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
458458
}
459459

460460
switch (sk->sk_state) {
461-
struct request_sock *req, **prev;
461+
struct request_sock *req;
462462
case TCP_LISTEN:
463463
if (sock_owned_by_user(sk))
464464
goto out;
465465

466-
req = inet_csk_search_req(sk, &prev, th->dest,
466+
req = inet_csk_search_req(sk, th->dest,
467467
iph->daddr, iph->saddr);
468468
if (!req)
469469
goto out;
@@ -484,7 +484,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
484484
* created socket, and POSIX does not want network
485485
* errors returned from accept().
486486
*/
487-
inet_csk_reqsk_queue_drop(sk, req, prev);
487+
inet_csk_reqsk_queue_drop(sk, req);
488488
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
489489
goto out;
490490

@@ -1392,15 +1392,14 @@ EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
13921392

13931393
static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
13941394
{
1395-
struct tcphdr *th = tcp_hdr(skb);
1395+
const struct tcphdr *th = tcp_hdr(skb);
13961396
const struct iphdr *iph = ip_hdr(skb);
1397+
struct request_sock *req;
13971398
struct sock *nsk;
1398-
struct request_sock **prev;
1399-
/* Find possible connection requests. */
1400-
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
1401-
iph->saddr, iph->daddr);
1399+
1400+
req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
14021401
if (req)
1403-
return tcp_check_req(sk, skb, req, prev, false);
1402+
return tcp_check_req(sk, skb, req, false);
14041403

14051404
nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
14061405
th->source, iph->daddr, th->dest, inet_iif(skb));

net/ipv4/tcp_minisocks.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,6 @@ EXPORT_SYMBOL(tcp_create_openreq_child);
572572

573573
struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
574574
struct request_sock *req,
575-
struct request_sock **prev,
576575
bool fastopen)
577576
{
578577
struct tcp_options_received tmp_opt;
@@ -766,7 +765,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
766765
if (child == NULL)
767766
goto listen_overflow;
768767

769-
inet_csk_reqsk_queue_unlink(sk, req, prev);
768+
inet_csk_reqsk_queue_unlink(sk, req);
770769
inet_csk_reqsk_queue_removed(sk, req);
771770

772771
inet_csk_reqsk_queue_add(sk, req, child);
@@ -791,7 +790,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
791790
tcp_reset(sk);
792791
}
793792
if (!fastopen) {
794-
inet_csk_reqsk_queue_drop(sk, req, prev);
793+
inet_csk_reqsk_queue_drop(sk, req);
795794
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
796795
}
797796
return NULL;

net/ipv6/inet6_connection_sock.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,20 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport,
113113
}
114114

115115
struct request_sock *inet6_csk_search_req(const struct sock *sk,
116-
struct request_sock ***prevp,
117116
const __be16 rport,
118117
const struct in6_addr *raddr,
119118
const struct in6_addr *laddr,
120119
const int iif)
121120
{
122121
const struct inet_connection_sock *icsk = inet_csk(sk);
123122
struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
124-
struct request_sock *req, **prev;
123+
struct request_sock *req;
125124

126-
for (prev = &lopt->syn_table[inet6_synq_hash(raddr, rport,
125+
for (req = lopt->syn_table[inet6_synq_hash(raddr, rport,
127126
lopt->hash_rnd,
128127
lopt->nr_table_entries)];
129-
(req = *prev) != NULL;
130-
prev = &req->dl_next) {
128+
req != NULL;
129+
req = req->dl_next) {
131130
const struct inet_request_sock *ireq = inet_rsk(req);
132131

133132
if (ireq->ir_rmt_port == rport &&
@@ -136,7 +135,6 @@ struct request_sock *inet6_csk_search_req(const struct sock *sk,
136135
ipv6_addr_equal(&ireq->ir_v6_loc_addr, laddr) &&
137136
(!ireq->ir_iif || ireq->ir_iif == iif)) {
138137
WARN_ON(req->sk != NULL);
139-
*prevp = prev;
140138
return req;
141139
}
142140
}

0 commit comments

Comments
 (0)