diff options
Diffstat (limited to 'net/rds/connection.c')
-rw-r--r-- | net/rds/connection.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/net/rds/connection.c b/net/rds/connection.c index d14445c48304..cc8b568c0c84 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
@@ -126,7 +126,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
126 | struct rds_transport *trans, gfp_t gfp, | 126 | struct rds_transport *trans, gfp_t gfp, |
127 | int is_outgoing) | 127 | int is_outgoing) |
128 | { | 128 | { |
129 | struct rds_connection *conn, *tmp, *parent = NULL; | 129 | struct rds_connection *conn, *parent = NULL; |
130 | struct hlist_head *head = rds_conn_bucket(laddr, faddr); | 130 | struct hlist_head *head = rds_conn_bucket(laddr, faddr); |
131 | unsigned long flags; | 131 | unsigned long flags; |
132 | int ret; | 132 | int ret; |
@@ -155,7 +155,6 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
155 | } | 155 | } |
156 | 156 | ||
157 | INIT_HLIST_NODE(&conn->c_hash_node); | 157 | INIT_HLIST_NODE(&conn->c_hash_node); |
158 | conn->c_version = RDS_PROTOCOL_3_0; | ||
159 | conn->c_laddr = laddr; | 158 | conn->c_laddr = laddr; |
160 | conn->c_faddr = faddr; | 159 | conn->c_faddr = faddr; |
161 | spin_lock_init(&conn->c_lock); | 160 | spin_lock_init(&conn->c_lock); |
@@ -211,26 +210,40 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, | |||
211 | trans->t_name ? trans->t_name : "[unknown]", | 210 | trans->t_name ? trans->t_name : "[unknown]", |
212 | is_outgoing ? "(outgoing)" : ""); | 211 | is_outgoing ? "(outgoing)" : ""); |
213 | 212 | ||
213 | /* | ||
214 | * Since we ran without holding the conn lock, someone could | ||
215 | * have created the same conn (either normal or passive) in the | ||
216 | * interim. We check while holding the lock. If we won, we complete | ||
217 | * init and return our conn. If we lost, we rollback and return the | ||
218 | * other one. | ||
219 | */ | ||
214 | spin_lock_irqsave(&rds_conn_lock, flags); | 220 | spin_lock_irqsave(&rds_conn_lock, flags); |
215 | if (parent == NULL) { | 221 | if (parent) { |
216 | tmp = rds_conn_lookup(head, laddr, faddr, trans); | 222 | /* Creating passive conn */ |
217 | if (tmp == NULL) | 223 | if (parent->c_passive) { |
218 | hlist_add_head(&conn->c_hash_node, head); | 224 | trans->conn_free(conn->c_transport_data); |
219 | } else { | 225 | kmem_cache_free(rds_conn_slab, conn); |
220 | tmp = parent->c_passive; | 226 | conn = parent->c_passive; |
221 | if (!tmp) | 227 | } else { |
222 | parent->c_passive = conn; | 228 | parent->c_passive = conn; |
223 | } | 229 | rds_cong_add_conn(conn); |
224 | 230 | rds_conn_count++; | |
225 | if (tmp) { | 231 | } |
226 | trans->conn_free(conn->c_transport_data); | ||
227 | kmem_cache_free(rds_conn_slab, conn); | ||
228 | conn = tmp; | ||
229 | } else { | 232 | } else { |
230 | rds_cong_add_conn(conn); | 233 | /* Creating normal conn */ |
231 | rds_conn_count++; | 234 | struct rds_connection *found; |
235 | |||
236 | found = rds_conn_lookup(head, laddr, faddr, trans); | ||
237 | if (found) { | ||
238 | trans->conn_free(conn->c_transport_data); | ||
239 | kmem_cache_free(rds_conn_slab, conn); | ||
240 | conn = found; | ||
241 | } else { | ||
242 | hlist_add_head(&conn->c_hash_node, head); | ||
243 | rds_cong_add_conn(conn); | ||
244 | rds_conn_count++; | ||
245 | } | ||
232 | } | 246 | } |
233 | |||
234 | spin_unlock_irqrestore(&rds_conn_lock, flags); | 247 | spin_unlock_irqrestore(&rds_conn_lock, flags); |
235 | 248 | ||
236 | out: | 249 | out: |
@@ -242,12 +255,14 @@ struct rds_connection *rds_conn_create(__be32 laddr, __be32 faddr, | |||
242 | { | 255 | { |
243 | return __rds_conn_create(laddr, faddr, trans, gfp, 0); | 256 | return __rds_conn_create(laddr, faddr, trans, gfp, 0); |
244 | } | 257 | } |
258 | EXPORT_SYMBOL_GPL(rds_conn_create); | ||
245 | 259 | ||
246 | struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr, | 260 | struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr, |
247 | struct rds_transport *trans, gfp_t gfp) | 261 | struct rds_transport *trans, gfp_t gfp) |
248 | { | 262 | { |
249 | return __rds_conn_create(laddr, faddr, trans, gfp, 1); | 263 | return __rds_conn_create(laddr, faddr, trans, gfp, 1); |
250 | } | 264 | } |
265 | EXPORT_SYMBOL_GPL(rds_conn_create_outgoing); | ||
251 | 266 | ||
252 | void rds_conn_destroy(struct rds_connection *conn) | 267 | void rds_conn_destroy(struct rds_connection *conn) |
253 | { | 268 | { |
@@ -290,6 +305,7 @@ void rds_conn_destroy(struct rds_connection *conn) | |||
290 | 305 | ||
291 | rds_conn_count--; | 306 | rds_conn_count--; |
292 | } | 307 | } |
308 | EXPORT_SYMBOL_GPL(rds_conn_destroy); | ||
293 | 309 | ||
294 | static void rds_conn_message_info(struct socket *sock, unsigned int len, | 310 | static void rds_conn_message_info(struct socket *sock, unsigned int len, |
295 | struct rds_info_iterator *iter, | 311 | struct rds_info_iterator *iter, |
@@ -393,6 +409,7 @@ void rds_for_each_conn_info(struct socket *sock, unsigned int len, | |||
393 | 409 | ||
394 | spin_unlock_irqrestore(&rds_conn_lock, flags); | 410 | spin_unlock_irqrestore(&rds_conn_lock, flags); |
395 | } | 411 | } |
412 | EXPORT_SYMBOL_GPL(rds_for_each_conn_info); | ||
396 | 413 | ||
397 | static int rds_conn_info_visitor(struct rds_connection *conn, | 414 | static int rds_conn_info_visitor(struct rds_connection *conn, |
398 | void *buffer) | 415 | void *buffer) |
@@ -468,6 +485,7 @@ void rds_conn_drop(struct rds_connection *conn) | |||
468 | atomic_set(&conn->c_state, RDS_CONN_ERROR); | 485 | atomic_set(&conn->c_state, RDS_CONN_ERROR); |
469 | queue_work(rds_wq, &conn->c_down_w); | 486 | queue_work(rds_wq, &conn->c_down_w); |
470 | } | 487 | } |
488 | EXPORT_SYMBOL_GPL(rds_conn_drop); | ||
471 | 489 | ||
472 | /* | 490 | /* |
473 | * An error occurred on the connection | 491 | * An error occurred on the connection |