aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-03-02 17:51:12 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-03-04 20:54:10 -0500
commitebbe442183b7b8192c963266f1c89048fefc63a5 (patch)
treec8d5621dcc0010161236ba3a6342d87f248cfde5
parent9bb4ca68fc48eea618b1af1c1cde2a251ae32d1b (diff)
iser-target: Fix command leak for tx_desc->comp_llnode_batch
This patch addresses a number of active I/O shutdown issues related to isert_cmd descriptors being leaked that are part of a completion interrupt coalescing batch. This includes adding logic in isert_cq_tx_comp_err() to drain any associated tx_desc->comp_llnode_batch, as well as isert_cq_drain_comp_llist() to drain any associated isert_conn->conn_comp_llist. Also, set tx_desc->llnode_active in isert_init_send_wr() in order to determine when work requests need to be skipped in isert_cq_tx_work() exception path code. Finally, update isert_init_send_wr() to only allow interrupt coalescing when ISER_CONN_UP. Acked-by: Sagi Grimberg <sagig@mellanox.com> Cc: Or Gerlitz <ogerlitz@mellanox.com> Cc: <stable@vger.kernel.org> #3.13+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c50
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h2
2 files changed, 46 insertions, 6 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 614a6ef6a79d..8ee228e9ab5a 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -497,7 +497,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
497 kref_init(&isert_conn->conn_kref); 497 kref_init(&isert_conn->conn_kref);
498 kref_get(&isert_conn->conn_kref); 498 kref_get(&isert_conn->conn_kref);
499 mutex_init(&isert_conn->conn_mutex); 499 mutex_init(&isert_conn->conn_mutex);
500 mutex_init(&isert_conn->conn_comp_mutex);
501 spin_lock_init(&isert_conn->conn_lock); 500 spin_lock_init(&isert_conn->conn_lock);
502 501
503 cma_id->context = isert_conn; 502 cma_id->context = isert_conn;
@@ -888,16 +887,17 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
888 * Coalesce send completion interrupts by only setting IB_SEND_SIGNALED 887 * Coalesce send completion interrupts by only setting IB_SEND_SIGNALED
889 * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. 888 * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls.
890 */ 889 */
891 mutex_lock(&isert_conn->conn_comp_mutex); 890 mutex_lock(&isert_conn->conn_mutex);
892 if (coalesce && 891 if (coalesce && isert_conn->state == ISER_CONN_UP &&
893 ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { 892 ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) {
893 tx_desc->llnode_active = true;
894 llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); 894 llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist);
895 mutex_unlock(&isert_conn->conn_comp_mutex); 895 mutex_unlock(&isert_conn->conn_mutex);
896 return; 896 return;
897 } 897 }
898 isert_conn->conn_comp_batch = 0; 898 isert_conn->conn_comp_batch = 0;
899 tx_desc->comp_llnode_batch = llist_del_all(&isert_conn->conn_comp_llist); 899 tx_desc->comp_llnode_batch = llist_del_all(&isert_conn->conn_comp_llist);
900 mutex_unlock(&isert_conn->conn_comp_mutex); 900 mutex_unlock(&isert_conn->conn_mutex);
901 901
902 send_wr->send_flags = IB_SEND_SIGNALED; 902 send_wr->send_flags = IB_SEND_SIGNALED;
903} 903}
@@ -1693,10 +1693,45 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
1693} 1693}
1694 1694
1695static void 1695static void
1696isert_cq_drain_comp_llist(struct isert_conn *isert_conn, struct ib_device *ib_dev)
1697{
1698 struct llist_node *llnode;
1699 struct isert_rdma_wr *wr;
1700 struct iser_tx_desc *t;
1701
1702 mutex_lock(&isert_conn->conn_mutex);
1703 llnode = llist_del_all(&isert_conn->conn_comp_llist);
1704 isert_conn->conn_comp_batch = 0;
1705 mutex_unlock(&isert_conn->conn_mutex);
1706
1707 while (llnode) {
1708 t = llist_entry(llnode, struct iser_tx_desc, comp_llnode);
1709 llnode = llist_next(llnode);
1710 wr = &t->isert_cmd->rdma_wr;
1711
1712 atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
1713 isert_completion_put(t, t->isert_cmd, ib_dev);
1714 }
1715}
1716
1717static void
1696isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) 1718isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
1697{ 1719{
1698 struct ib_device *ib_dev = isert_conn->conn_cm_id->device; 1720 struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
1699 struct isert_cmd *isert_cmd = tx_desc->isert_cmd; 1721 struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
1722 struct llist_node *llnode = tx_desc->comp_llnode_batch;
1723 struct isert_rdma_wr *wr;
1724 struct iser_tx_desc *t;
1725
1726 while (llnode) {
1727 t = llist_entry(llnode, struct iser_tx_desc, comp_llnode);
1728 llnode = llist_next(llnode);
1729 wr = &t->isert_cmd->rdma_wr;
1730
1731 atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
1732 isert_completion_put(t, t->isert_cmd, ib_dev);
1733 }
1734 tx_desc->comp_llnode_batch = NULL;
1700 1735
1701 if (!isert_cmd) 1736 if (!isert_cmd)
1702 isert_unmap_tx_desc(tx_desc, ib_dev); 1737 isert_unmap_tx_desc(tx_desc, ib_dev);
@@ -1713,6 +1748,8 @@ isert_cq_rx_comp_err(struct isert_conn *isert_conn)
1713 if (isert_conn->post_recv_buf_count) 1748 if (isert_conn->post_recv_buf_count)
1714 return; 1749 return;
1715 1750
1751 isert_cq_drain_comp_llist(isert_conn, ib_dev);
1752
1716 if (conn->sess) { 1753 if (conn->sess) {
1717 target_sess_cmd_list_set_waiting(conn->sess->se_sess); 1754 target_sess_cmd_list_set_waiting(conn->sess->se_sess);
1718 target_wait_for_sess_cmds(conn->sess->se_sess); 1755 target_wait_for_sess_cmds(conn->sess->se_sess);
@@ -1752,6 +1789,9 @@ isert_cq_tx_work(struct work_struct *work)
1752 pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); 1789 pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err);
1753 1790
1754 if (wc.wr_id != ISER_FASTREG_LI_WRID) { 1791 if (wc.wr_id != ISER_FASTREG_LI_WRID) {
1792 if (tx_desc->llnode_active)
1793 continue;
1794
1755 atomic_dec(&isert_conn->post_send_buf_count); 1795 atomic_dec(&isert_conn->post_send_buf_count);
1756 isert_cq_tx_comp_err(tx_desc, isert_conn); 1796 isert_cq_tx_comp_err(tx_desc, isert_conn);
1757 } 1797 }
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index 10be55a3185e..f6ae7f5dd408 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -46,6 +46,7 @@ struct iser_tx_desc {
46 struct isert_cmd *isert_cmd; 46 struct isert_cmd *isert_cmd;
47 struct llist_node *comp_llnode_batch; 47 struct llist_node *comp_llnode_batch;
48 struct llist_node comp_llnode; 48 struct llist_node comp_llnode;
49 bool llnode_active;
49 struct ib_send_wr send_wr; 50 struct ib_send_wr send_wr;
50} __packed; 51} __packed;
51 52
@@ -127,7 +128,6 @@ struct isert_conn {
127#define ISERT_COMP_BATCH_COUNT 8 128#define ISERT_COMP_BATCH_COUNT 8
128 int conn_comp_batch; 129 int conn_comp_batch;
129 struct llist_head conn_comp_llist; 130 struct llist_head conn_comp_llist;
130 struct mutex conn_comp_mutex;
131}; 131};
132 132
133#define ISERT_MAX_CQ 64 133#define ISERT_MAX_CQ 64