Hi Jiri, Just send out an updated version of this patch that applies against 3.12.18 as well. Thanks! --nab On Tue, 2014-05-06 at 11:19 +0200, Jiri Slaby wrote: > From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> > > This patch does NOT apply to the 3.12 stable tree. If you still want > it applied, please provide a backport. > > =============== > > commit 03e7848a64ed535a30f5d7fc6dede2d5a6a2534b upstream. > > This patch fixes a bug where outstanding RDMA_READs with WRITE_PENDING > status require an extra target_put_sess_cmd() in isert_put_cmd() code > when called from isert_cq_tx_comp_err() + isert_cq_drain_comp_llist() > context during session shutdown. > > The extra kref PUT is required so that transport_generic_free_cmd() > invokes the last target_put_sess_cmd() -> target_release_cmd_kref(), > which will complete(&se_cmd->cmd_wait_comp) the outstanding se_cmd > descriptor with WRITE_PENDING status, and awake the completion in > target_wait_for_sess_cmds() to invoke TFO->release_cmd(). > > The bug was manifesting itself in target_wait_for_sess_cmds() where > a se_cmd descriptor with WRITE_PENDING status would end up sleeping > indefinately. > > Acked-by: Sagi Grimberg <sagig@xxxxxxxxxxxx> > Cc: Or Gerlitz <ogerlitz@xxxxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> #3.10+ > Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> > --- > drivers/infiniband/ulp/isert/ib_isert.c | 37 +++++++++++++++++++++++---------- > 1 file changed, 26 insertions(+), 11 deletions(-) > > diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c > index 18ada7fb0fc9..f7801aeb7628 100644 > --- a/drivers/infiniband/ulp/isert/ib_isert.c > +++ b/drivers/infiniband/ulp/isert/ib_isert.c > @@ -1580,7 +1580,7 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) > } > > static void > -isert_put_cmd(struct isert_cmd *isert_cmd) > +isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) > { > struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; > struct isert_conn *isert_conn = isert_cmd->conn; > @@ -1596,8 +1596,21 @@ isert_put_cmd(struct isert_cmd *isert_cmd) > list_del_init(&cmd->i_conn_node); > spin_unlock_bh(&conn->cmd_lock); > > - if (cmd->data_direction == DMA_TO_DEVICE) > + if (cmd->data_direction == DMA_TO_DEVICE) { > iscsit_stop_dataout_timer(cmd); > + /* > + * Check for special case during comp_err where > + * WRITE_PENDING has been handed off from core, > + * but requires an extra target_put_sess_cmd() > + * before transport_generic_free_cmd() below. > + */ > + if (comp_err && > + cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { > + struct se_cmd *se_cmd = &cmd->se_cmd; > + > + target_put_sess_cmd(se_cmd->se_sess, se_cmd); > + } > + } > > device->unreg_rdma_mem(isert_cmd, isert_conn); > transport_generic_free_cmd(&cmd->se_cmd, 0); > @@ -1652,7 +1665,7 @@ isert_unmap_tx_desc(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev) > > static void > isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, > - struct ib_device *ib_dev) > + struct ib_device *ib_dev, bool comp_err) > { > if (isert_cmd->pdu_buf_dma != 0) { > pr_debug("Calling ib_dma_unmap_single for isert_cmd->pdu_buf_dma\n"); > @@ -1662,7 +1675,7 @@ isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, > } > > isert_unmap_tx_desc(tx_desc, ib_dev); > - isert_put_cmd(isert_cmd); > + isert_put_cmd(isert_cmd, comp_err); > } > > static int > @@ -1787,14 +1800,14 @@ isert_do_control_comp(struct work_struct *work) > iscsit_tmr_post_handler(cmd, cmd->conn); > > cmd->i_state = ISTATE_SENT_STATUS; > - isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); > + isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); > break; > case ISTATE_SEND_REJECT: > pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n"); > atomic_dec(&isert_conn->post_send_buf_count); > > cmd->i_state = ISTATE_SENT_STATUS; > - isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); > + isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); > break; > case ISTATE_SEND_LOGOUTRSP: > pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); > @@ -1808,7 +1821,7 @@ isert_do_control_comp(struct work_struct *work) > case ISTATE_SEND_TEXTRSP: > atomic_dec(&isert_conn->post_send_buf_count); > cmd->i_state = ISTATE_SENT_STATUS; > - isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); > + isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); > break; > default: > pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); > @@ -1850,7 +1863,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc, > atomic_dec(&isert_conn->post_send_buf_count); > > cmd->i_state = ISTATE_SENT_STATUS; > - isert_completion_put(tx_desc, isert_cmd, ib_dev); > + isert_completion_put(tx_desc, isert_cmd, ib_dev, false); > } > > static void > @@ -1943,7 +1956,8 @@ isert_cq_drain_comp_llist(struct isert_conn *isert_conn, struct ib_device *ib_de > &isert_conn->post_send_buf_count); > else > atomic_dec(&isert_conn->post_send_buf_count); > - isert_completion_put(t, t->isert_cmd, ib_dev); > + > + isert_completion_put(t, t->isert_cmd, ib_dev, true); > } > } > > @@ -1973,14 +1987,15 @@ isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn > &isert_conn->post_send_buf_count); > else > atomic_dec(&isert_conn->post_send_buf_count); > - isert_completion_put(t, t->isert_cmd, ib_dev); > + > + isert_completion_put(t, t->isert_cmd, ib_dev, true); > } > tx_desc->comp_llnode_batch = NULL; > > if (!isert_cmd) > isert_unmap_tx_desc(tx_desc, ib_dev); > else > - isert_completion_put(tx_desc, isert_cmd, ib_dev); > + isert_completion_put(tx_desc, isert_cmd, ib_dev, true); > } > > static void -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html