rds_sock_count--;
        spin_unlock_irqrestore(&rds_sock_lock, flags);
 
+       rds_trans_put(rs->rs_transport);
+
        sock->sk = NULL;
        sock_put(sk);
 out:
 
 {
        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;
 
         * 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
 
 int rds_trans_register(struct rds_transport *trans);
 void rds_trans_unregister(struct rds_transport *trans);
 struct rds_transport *rds_trans_get_preferred(__be32 addr);
+void rds_trans_put(struct rds_transport *trans);
 unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
                                       unsigned int avail);
 int rds_trans_init(void);
 
 }
 EXPORT_SYMBOL_GPL(rds_trans_unregister);
 
+void rds_trans_put(struct rds_transport *trans)
+{
+       if (trans && trans->t_owner)
+               module_put(trans->t_owner);
+}
+
 struct rds_transport *rds_trans_get_preferred(__be32 addr)
 {
        struct rds_transport *ret = NULL;
-       int i;
+       struct rds_transport *trans;
+       unsigned int i;
 
        if (IN_LOOPBACK(ntohl(addr)))
                return &rds_loop_transport;
 
        down_read(&rds_trans_sem);
-       for (i = 0; i < RDS_TRANS_COUNT; i++)
-       {
-               if (transports[i] && (transports[i]->laddr_check(addr) == 0)) {
-                       ret = transports[i];
+       for (i = 0; i < RDS_TRANS_COUNT; i++) {
+               trans = transports[i];
+
+               if (trans && (trans->laddr_check(addr) == 0) &&
+                   (!trans->t_owner || try_module_get(trans->t_owner))) {
+                       ret = trans;
                        break;
                }
        }