aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rds/connection.c')
-rw-r--r--net/rds/connection.c54
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
236out: 249out:
@@ -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}
258EXPORT_SYMBOL_GPL(rds_conn_create);
245 259
246struct rds_connection *rds_conn_create_outgoing(__be32 laddr, __be32 faddr, 260struct 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}
265EXPORT_SYMBOL_GPL(rds_conn_create_outgoing);
251 266
252void rds_conn_destroy(struct rds_connection *conn) 267void 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}
308EXPORT_SYMBOL_GPL(rds_conn_destroy);
293 309
294static void rds_conn_message_info(struct socket *sock, unsigned int len, 310static 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}
412EXPORT_SYMBOL_GPL(rds_for_each_conn_info);
396 413
397static int rds_conn_info_visitor(struct rds_connection *conn, 414static 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}
488EXPORT_SYMBOL_GPL(rds_conn_drop);
471 489
472/* 490/*
473 * An error occurred on the connection 491 * An error occurred on the connection