summary refs log tree commit diff
path: root/net/rds/connection.c
diff options
context:
space:
mode:
authorZach Brown <zach.brown@oracle.com>2010-07-23 10:32:31 -0700
committerAndy Grover <andy.grover@oracle.com>2010-09-08 18:16:47 -0700
commit5adb5bc65f93e52341c3fc9d03d4030dd375e256 (patch)
tree55b19c7757ccd64f58169a05cd63e91bee409bad /net/rds/connection.c
parent77510481c0c3980c8979ed236d63e59221fb8ce5 (diff)
downloadlinux-5adb5bc65f93e52341c3fc9d03d4030dd375e256.tar.gz
RDS: have sockets get transport module references
Right now there's nothing to stop the various paths that use
rs->rs_transport from racing with rmmod and executing freed transport
code.  The simple fix is to have binding to a transport also hold a
reference to the transport's module, removing this class of races.

We already had an unused t_owner field which was set for the modular
transports and which wasn't set for the built-in loop transport.

Signed-off-by: Zach Brown <zach.brown@oracle.com>
Diffstat (limited to 'net/rds/connection.c')
-rw-r--r--net/rds/connection.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 75a1a37d64d3..968b7a798398 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -117,6 +117,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
 {
 	struct rds_connection *conn, *parent = NULL;
 	struct hlist_head *head = rds_conn_bucket(laddr, faddr);
+	struct rds_transport *loop_trans;
 	unsigned long flags;
 	int ret;
 
@@ -163,7 +164,9 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
 	 * can bind to the destination address then we'd rather the messages
 	 * flow through loopback rather than either transport.
 	 */
-	if (rds_trans_get_preferred(faddr)) {
+	loop_trans = rds_trans_get_preferred(faddr);
+	if (loop_trans) {
+		rds_trans_put(loop_trans);
 		conn->c_loopback = 1;
 		if (is_outgoing && trans->t_prefer_loopback) {
 			/* "outgoing" connection - and the transport