diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-03-02 17:51:12 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-03-04 20:54:10 -0500 |
commit | ebbe442183b7b8192c963266f1c89048fefc63a5 (patch) | |
tree | c8d5621dcc0010161236ba3a6342d87f248cfde5 | |
parent | 9bb4ca68fc48eea618b1af1c1cde2a251ae32d1b (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.c | 50 | ||||
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.h | 2 |
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 | ||
1695 | static void | 1695 | static void |
1696 | isert_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 | |||
1717 | static void | ||
1696 | isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) | 1718 | isert_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 |