struct rds_connection *conn;
};
+struct rds_ib_conn_destroy_work {
+ struct delayed_work work;
+ struct rds_connection *conn;
+};
+
struct rds_ib_addr_change_work {
struct delayed_work work;
__be32 addr;
void rds_ib_cm_connect_complete(struct rds_connection *conn,
struct rdma_cm_event *event);
void rds_ib_init_frag(unsigned int version);
+void rds_ib_conn_destroy_init(struct rds_connection *conn);
#define rds_ib_conn_error(conn, fmt...) \
__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
if (conn->c_version < RDS_PROTOCOL_VERSION) {
if (conn->c_version != RDS_PROTOCOL_COMPAT_VERSION) {
- /*
- * BUG: destroying connection here can deadlock with
- * the CM event handler on the c_cm_lock.
- */
printk(KERN_NOTICE "RDS/IB: Connection to"
" %u.%u.%u.%u version %u.%u failed,"
" no longer supported\n",
NIPQUAD(conn->c_faddr),
RDS_PROTOCOL_MAJOR(conn->c_version),
RDS_PROTOCOL_MINOR(conn->c_version));
- rds_conn_destroy(conn);
+ rds_ib_conn_destroy_init(conn);
return;
}
}
return destroy;
}
+void rds_ib_conn_destroy_worker(struct work_struct *_work)
+{
+ struct rds_ib_conn_destroy_work *work =
+ container_of(_work, struct rds_ib_conn_destroy_work, work.work);
+ struct rds_connection *conn = work->conn;
+
+ rds_conn_destroy(conn);
+
+ kfree(work);
+}
+
+void rds_ib_conn_destroy_init(struct rds_connection *conn)
+{
+ struct rds_ib_conn_destroy_work *work;
+
+ work = kzalloc(sizeof *work, GFP_ATOMIC);
+ if (!work) {
+ pr_err("RDS/IB: failed to allocate connection destroy work\n");
+ return;
+ }
+
+ work->conn = conn;
+ INIT_DELAYED_WORK(&work->work, rds_ib_conn_destroy_worker);
+ queue_delayed_work(rds_aux_wq, &work->work, 0);
+}
int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
{