inet: add rsk_listener field to struct request_sock
authorEric Dumazet <edumazet@google.com>
Wed, 18 Mar 2015 01:32:28 +0000 (18:32 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Mar 2015 02:01:56 +0000 (22:01 -0400)
Once we'll be able to lookup request sockets in ehash table,
we'll need to get access to listener which created this request.

This avoid doing a lookup to find the listener, which benefits
for a more solid SO_REUSEPORT, and is needed once we no
longer queue request sock into a listener private queue.

Note that 'struct tcp_request_sock'->listener could be reduced
to a single bit, as TFO listener should match req->rsk_listener.
TFO will no longer need to hold a reference on the listener.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/request_sock.h
net/ipv4/tcp_input.c

index 56dc2faba47ec6fa3faa64224e4e1481057058fa..723d1cbdf20ebe4f31ff70f6fe97fccaac675d50 100644 (file)
@@ -52,6 +52,7 @@ struct request_sock {
 #define rsk_refcnt                     __req_common.skc_refcnt
 
        struct request_sock             *dl_next;
+       struct sock                     *rsk_listener;
        u16                             mss;
        u8                              num_retrans; /* number of retransmits */
        u8                              cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
@@ -67,13 +68,16 @@ struct request_sock {
        u32                             peer_secid;
 };
 
-static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops)
+static inline struct request_sock *
+reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener)
 {
        struct request_sock *req = kmem_cache_alloc(ops->slab, GFP_ATOMIC);
 
-       if (req != NULL)
+       if (req) {
                req->rsk_ops = ops;
-
+               sock_hold(sk_listener);
+               req->rsk_listener = sk_listener;
+       }
        return req;
 }
 
@@ -88,6 +92,8 @@ static inline void reqsk_free(struct request_sock *req)
        WARN_ON_ONCE(atomic_read(&req->rsk_refcnt) != 0);
 
        req->rsk_ops->destructor(req);
+       if (req->rsk_listener)
+               sock_put(req->rsk_listener);
        kmem_cache_free(req->rsk_ops->slab, req);
 }
 
index 52b74e0eab2a81ccfca1918074fda5b962a30c77..fbe518981d36bbe4539d7abd90c839d1f83f262a 100644 (file)
@@ -5970,7 +5970,7 @@ static void tcp_openreq_init(struct request_sock *req,
 struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
                                      struct sock *sk_listener)
 {
-       struct request_sock *req = reqsk_alloc(ops);
+       struct request_sock *req = reqsk_alloc(ops, sk_listener);
 
        if (req) {
                struct inet_request_sock *ireq = inet_rsk(req);