diff options
author | Eric Dumazet <edumazet@google.com> | 2016-04-01 11:52:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-04 22:11:19 -0400 |
commit | 3a5d1c0e7cb5ba91aabbd7e28626e3cc925f8093 (patch) | |
tree | 14db12b0567eaaa34d3d9850645daf8b54e8689f /include/net | |
parent | 2d331915a04144dad738e725769d8fac06ef6155 (diff) |
inet: reqsk_alloc() needs to take care of dead listeners
We'll soon no longer take a refcount on listeners,
so reqsk_alloc() can not assume a listener refcount is not
zero. We need to use atomic_inc_not_zero()
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/request_sock.h | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/include/net/request_sock.h b/include/net/request_sock.h index f49759decb28..6ebe13eb1c4c 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h | |||
@@ -85,24 +85,23 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener, | |||
85 | struct request_sock *req; | 85 | struct request_sock *req; |
86 | 86 | ||
87 | req = kmem_cache_alloc(ops->slab, GFP_ATOMIC | __GFP_NOWARN); | 87 | req = kmem_cache_alloc(ops->slab, GFP_ATOMIC | __GFP_NOWARN); |
88 | 88 | if (!req) | |
89 | if (req) { | 89 | return NULL; |
90 | req->rsk_ops = ops; | 90 | req->rsk_listener = NULL; |
91 | if (attach_listener) { | 91 | if (attach_listener) { |
92 | sock_hold(sk_listener); | 92 | if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) { |
93 | req->rsk_listener = sk_listener; | 93 | kmem_cache_free(ops->slab, req); |
94 | } else { | 94 | return NULL; |
95 | req->rsk_listener = NULL; | ||
96 | } | 95 | } |
97 | req_to_sk(req)->sk_prot = sk_listener->sk_prot; | 96 | req->rsk_listener = sk_listener; |
98 | sk_node_init(&req_to_sk(req)->sk_node); | ||
99 | sk_tx_queue_clear(req_to_sk(req)); | ||
100 | req->saved_syn = NULL; | ||
101 | /* Following is temporary. It is coupled with debugging | ||
102 | * helpers in reqsk_put() & reqsk_free() | ||
103 | */ | ||
104 | atomic_set(&req->rsk_refcnt, 0); | ||
105 | } | 97 | } |
98 | req->rsk_ops = ops; | ||
99 | req_to_sk(req)->sk_prot = sk_listener->sk_prot; | ||
100 | sk_node_init(&req_to_sk(req)->sk_node); | ||
101 | sk_tx_queue_clear(req_to_sk(req)); | ||
102 | req->saved_syn = NULL; | ||
103 | atomic_set(&req->rsk_refcnt, 0); | ||
104 | |||
106 | return req; | 105 | return req; |
107 | } | 106 | } |
108 | 107 | ||