diff --git a/iscsi-scst/kernel/isert-scst/iser.h b/iscsi-scst/kernel/isert-scst/iser.h index e0ba95d6c..d4cde7d98 100644 --- a/iscsi-scst/kernel/isert-scst/iser.h +++ b/iscsi-scst/kernel/isert-scst/iser.h @@ -161,6 +161,7 @@ struct isert_connection { unsigned long flags; struct work_struct close_work; + struct work_struct drain_work; struct isert_wr drain_wr; struct kref kref; diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index 700beb328..6531c750c 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -486,6 +486,36 @@ static const char *wr_status_str(enum ib_wc_status status) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void isert_conn_drained_do_work(void *ctx) +#else +static void isert_conn_drained_do_work(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct isert_connection *isert_conn = ctx; +#else + struct isert_connection *isert_conn = + container_of(work, struct isert_connection, drain_work); +#endif + + /* notify upper layer */ + if (!test_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags)) + isert_connection_closed(&isert_conn->iscsi); + + isert_conn_free(isert_conn); +} + +static void isert_sched_conn_drained(struct isert_connection *isert_conn) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&isert_conn->drain_work, isert_conn_drained_do_work, isert_conn); +#else + INIT_WORK(&isert_conn->drain_work, isert_conn_drained_do_work); +#endif + isert_conn_queue_work(&isert_conn->drain_work); +} + static void isert_handle_wc_error(struct ib_wc *wc) { struct isert_wr *wr = _u64_to_ptr(wc->wr_id); @@ -502,10 +532,7 @@ static void isert_handle_wc_error(struct ib_wc *wc) switch (wr->wr_op) { case ISER_WR_SEND: if (unlikely(wr->send_wr.num_sge == 0)) { /* Drain WR */ - /* notify upper layer */ - if (!test_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags)) - isert_connection_closed(&isert_conn->iscsi); - isert_conn_free(isert_conn); + isert_sched_conn_drained(isert_conn); } else { isert_pdu_err(&isert_pdu->iscsi); } @@ -1063,8 +1090,6 @@ fail_get: return ERR_PTR(err); } -/* start closing process; - * only when all buffers released, can free */ static void isert_kref_free(struct kref *kref) { struct isert_connection *isert_conn = container_of(kref, @@ -1077,8 +1102,6 @@ static void isert_kref_free(struct kref *kref) pr_info("isert_conn_free conn:%p\n", isert_conn); - flush_workqueue(isert_conn->cq_desc->cq_workqueue); - isert_free_conn_resources(isert_conn); isert_conn_qp_destroy(isert_conn); diff --git a/iscsi-scst/kernel/isert-scst/isert.c b/iscsi-scst/kernel/isert-scst/isert.c index 1a6d44285..a26abfeef 100644 --- a/iscsi-scst/kernel/isert-scst/isert.c +++ b/iscsi-scst/kernel/isert-scst/isert.c @@ -269,7 +269,7 @@ static int isert_conn_activate(struct iscsi_conn *conn) return 0; } -static void isert_conn_free(struct iscsi_conn *conn) +static void isert_free_conn(struct iscsi_conn *conn) { isert_free_connection(conn); } @@ -452,7 +452,7 @@ static struct iscsit_transport isert_transport = { .transport_type = ISCSI_RDMA, .iscsit_conn_alloc = isert_conn_alloc, .iscsit_conn_activate = isert_conn_activate, - .iscsit_conn_free = isert_conn_free, + .iscsit_conn_free = isert_free_conn, .iscsit_alloc_cmd = isert_cmnd_alloc, .iscsit_free_cmd = isert_cmnd_free, .iscsit_preprocessing_done = isert_preprocessing_done,