]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: IB: invoke connection destruction in worker
authorAjaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
Thu, 14 Apr 2016 20:58:46 +0000 (13:58 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Tue, 12 Jul 2016 19:49:35 +0000 (12:49 -0700)
This is to avoid deadlock with c_cm_lock mutex.
In event handling path of Infiniband, whenever connection destruction is
required; we should invoke worker in order to avoid deadlock with mutex.

Orabug: 23222944

Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
net/rds/ib.h
net/rds/ib_cm.c

index c1c7a629a2e7fc5e1e597ff3369f640184669b81..0202c1c8f4794ea3060d6db57a6fd9ff46109177 100644 (file)
@@ -406,6 +406,11 @@ struct rds_ib_conn_drop_work {
        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;
@@ -581,6 +586,7 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id);
 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)
index 316383fc464749c5cd82b602549d77c251939393..0c99711240cd71b5d0ef5181a7946d168815a1c0 100644 (file)
@@ -220,17 +220,13 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
 
        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;
                }
        }
@@ -989,6 +985,31 @@ out:
        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)
 {