aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBryant G. Ly <bryantly@linux.vnet.ibm.com>2017-05-05 15:17:15 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2017-05-05 23:24:43 -0400
commit25e78531268e9240fc594ce76587601b873d37c9 (patch)
treec566a4f7b78f9a23c778741703f3534f1d653116 /drivers
parentd906d8af28e524bfa62c49cb2315f6ccdb910938 (diff)
ibmvscsis: Do not send aborted task response
The driver is sending a response to the actual scsi op that was aborted by an abort task TM, while LIO is sending a response to the abort task TM. ibmvscsis_tgt does not send the response to the client until release_cmd time. The reason for this was because if we did it at queue_status time, then the client would be free to reuse the tag for that command, but we're still using the tag until the command is released at release_cmd time, so we chose to delay sending the response until then. That then caused this issue, because release_cmd is always called, even if queue_status is not. SCSI spec says that the initiator that sends the abort task TM NEVER gets a response to the aborted op and with the current code it will send a response. Thus this fix will remove that response if the CMD_T_ABORTED && !CMD_T_TAS. Another case with a small timing window is the case where if LIO sends a TMR_DOES_NOT_EXIST, and the release_cmd callback is called for the TMR Abort cmd before the release_cmd for the (attemped) aborted cmd, then we need to ensure that we send the response for the (attempted) abort cmd to the client before we send the response for the TMR Abort cmd. Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com> Signed-off-by: Michael Cyr <mikecyr@linux.vnet.ibm.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c114
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h2
2 files changed, 91 insertions, 25 deletions
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index 0f807798c624..d390325c99ec 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -1170,6 +1170,7 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
1170 cmd = list_first_entry_or_null(&vscsi->free_cmd, 1170 cmd = list_first_entry_or_null(&vscsi->free_cmd,
1171 struct ibmvscsis_cmd, list); 1171 struct ibmvscsis_cmd, list);
1172 if (cmd) { 1172 if (cmd) {
1173 cmd->flags &= ~(DELAY_SEND);
1173 list_del(&cmd->list); 1174 list_del(&cmd->list);
1174 cmd->iue = iue; 1175 cmd->iue = iue;
1175 cmd->type = UNSET_TYPE; 1176 cmd->type = UNSET_TYPE;
@@ -1749,45 +1750,79 @@ static void srp_snd_msg_failed(struct scsi_info *vscsi, long rc)
1749static void ibmvscsis_send_messages(struct scsi_info *vscsi) 1750static void ibmvscsis_send_messages(struct scsi_info *vscsi)
1750{ 1751{
1751 u64 msg_hi = 0; 1752 u64 msg_hi = 0;
1752 /* note do not attmempt to access the IU_data_ptr with this pointer 1753 /* note do not attempt to access the IU_data_ptr with this pointer
1753 * it is not valid 1754 * it is not valid
1754 */ 1755 */
1755 struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi; 1756 struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi;
1756 struct ibmvscsis_cmd *cmd, *nxt; 1757 struct ibmvscsis_cmd *cmd, *nxt;
1757 struct iu_entry *iue; 1758 struct iu_entry *iue;
1758 long rc = ADAPT_SUCCESS; 1759 long rc = ADAPT_SUCCESS;
1760 bool retry = false;
1759 1761
1760 if (!(vscsi->flags & RESPONSE_Q_DOWN)) { 1762 if (!(vscsi->flags & RESPONSE_Q_DOWN)) {
1761 list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) { 1763 do {
1762 iue = cmd->iue; 1764 retry = false;
1765 list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp,
1766 list) {
1767 /*
1768 * Check to make sure abort cmd gets processed
1769 * prior to the abort tmr cmd
1770 */
1771 if (cmd->flags & DELAY_SEND)
1772 continue;
1763 1773
1764 crq->valid = VALID_CMD_RESP_EL; 1774 if (cmd->abort_cmd) {
1765 crq->format = cmd->rsp.format; 1775 retry = true;
1776 cmd->abort_cmd->flags &= ~(DELAY_SEND);
1777 }
1766 1778
1767 if (cmd->flags & CMD_FAST_FAIL) 1779 /*
1768 crq->status = VIOSRP_ADAPTER_FAIL; 1780 * If CMD_T_ABORTED w/o CMD_T_TAS scenarios and
1781 * the case where LIO issued a
1782 * ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST
1783 * case then we dont send a response, since it
1784 * was already done.
1785 */
1786 if (cmd->se_cmd.transport_state & CMD_T_ABORTED &&
1787 !(cmd->se_cmd.transport_state & CMD_T_TAS)) {
1788 list_del(&cmd->list);
1789 ibmvscsis_free_cmd_resources(vscsi,
1790 cmd);
1791 } else {
1792 iue = cmd->iue;
1769 1793
1770 crq->IU_length = cpu_to_be16(cmd->rsp.len); 1794 crq->valid = VALID_CMD_RESP_EL;
1795 crq->format = cmd->rsp.format;
1771 1796
1772 rc = h_send_crq(vscsi->dma_dev->unit_address, 1797 if (cmd->flags & CMD_FAST_FAIL)
1773 be64_to_cpu(msg_hi), 1798 crq->status = VIOSRP_ADAPTER_FAIL;
1774 be64_to_cpu(cmd->rsp.tag));
1775 1799
1776 pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n", 1800 crq->IU_length = cpu_to_be16(cmd->rsp.len);
1777 cmd, be64_to_cpu(cmd->rsp.tag), rc);
1778 1801
1779 /* if all ok free up the command element resources */ 1802 rc = h_send_crq(vscsi->dma_dev->unit_address,
1780 if (rc == H_SUCCESS) { 1803 be64_to_cpu(msg_hi),
1781 /* some movement has occurred */ 1804 be64_to_cpu(cmd->rsp.tag));
1782 vscsi->rsp_q_timer.timer_pops = 0;
1783 list_del(&cmd->list);
1784 1805
1785 ibmvscsis_free_cmd_resources(vscsi, cmd); 1806 pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n",
1786 } else { 1807 cmd, be64_to_cpu(cmd->rsp.tag), rc);
1787 srp_snd_msg_failed(vscsi, rc); 1808
1788 break; 1809 /* if all ok free up the command
1810 * element resources
1811 */
1812 if (rc == H_SUCCESS) {
1813 /* some movement has occurred */
1814 vscsi->rsp_q_timer.timer_pops = 0;
1815 list_del(&cmd->list);
1816
1817 ibmvscsis_free_cmd_resources(vscsi,
1818 cmd);
1819 } else {
1820 srp_snd_msg_failed(vscsi, rc);
1821 break;
1822 }
1823 }
1789 } 1824 }
1790 } 1825 } while (retry);
1791 1826
1792 if (!rc) { 1827 if (!rc) {
1793 /* 1828 /*
@@ -2708,6 +2743,7 @@ static int ibmvscsis_alloc_cmds(struct scsi_info *vscsi, int num)
2708 2743
2709 for (i = 0, cmd = (struct ibmvscsis_cmd *)vscsi->cmd_pool; i < num; 2744 for (i = 0, cmd = (struct ibmvscsis_cmd *)vscsi->cmd_pool; i < num;
2710 i++, cmd++) { 2745 i++, cmd++) {
2746 cmd->abort_cmd = NULL;
2711 cmd->adapter = vscsi; 2747 cmd->adapter = vscsi;
2712 INIT_WORK(&cmd->work, ibmvscsis_scheduler); 2748 INIT_WORK(&cmd->work, ibmvscsis_scheduler);
2713 list_add_tail(&cmd->list, &vscsi->free_cmd); 2749 list_add_tail(&cmd->list, &vscsi->free_cmd);
@@ -3579,9 +3615,20 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
3579{ 3615{
3580 struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, 3616 struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
3581 se_cmd); 3617 se_cmd);
3618 struct scsi_info *vscsi = cmd->adapter;
3582 struct iu_entry *iue = cmd->iue; 3619 struct iu_entry *iue = cmd->iue;
3583 int rc; 3620 int rc;
3584 3621
3622 /*
3623 * If CLIENT_FAILED OR RESPONSE_Q_DOWN, then just return success
3624 * since LIO can't do anything about it, and we dont want to
3625 * attempt an srp_transfer_data.
3626 */
3627 if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) {
3628 pr_err("write_pending failed since: %d\n", vscsi->flags);
3629 return 0;
3630 }
3631
3585 rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 3632 rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma,
3586 1, 1); 3633 1, 1);
3587 if (rc) { 3634 if (rc) {
@@ -3660,11 +3707,28 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd)
3660 struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd, 3707 struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
3661 se_cmd); 3708 se_cmd);
3662 struct scsi_info *vscsi = cmd->adapter; 3709 struct scsi_info *vscsi = cmd->adapter;
3710 struct ibmvscsis_cmd *cmd_itr;
3711 struct iu_entry *iue = iue = cmd->iue;
3712 struct srp_tsk_mgmt *srp_tsk = &vio_iu(iue)->srp.tsk_mgmt;
3713 u64 tag_to_abort = be64_to_cpu(srp_tsk->task_tag);
3663 uint len; 3714 uint len;
3664 3715
3665 pr_debug("queue_tm_rsp %p, status %d\n", 3716 pr_debug("queue_tm_rsp %p, status %d\n",
3666 se_cmd, (int)se_cmd->se_tmr_req->response); 3717 se_cmd, (int)se_cmd->se_tmr_req->response);
3667 3718
3719 if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK &&
3720 cmd->se_cmd.se_tmr_req->response == TMR_TASK_DOES_NOT_EXIST) {
3721 spin_lock_bh(&vscsi->intr_lock);
3722 list_for_each_entry(cmd_itr, &vscsi->active_q, list) {
3723 if (tag_to_abort == cmd_itr->se_cmd.tag) {
3724 cmd_itr->abort_cmd = cmd;
3725 cmd->flags |= DELAY_SEND;
3726 break;
3727 }
3728 }
3729 spin_unlock_bh(&vscsi->intr_lock);
3730 }
3731
3668 srp_build_response(vscsi, cmd, &len); 3732 srp_build_response(vscsi, cmd, &len);
3669 cmd->rsp.format = SRP_FORMAT; 3733 cmd->rsp.format = SRP_FORMAT;
3670 cmd->rsp.len = len; 3734 cmd->rsp.len = len;
@@ -3672,8 +3736,8 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd)
3672 3736
3673static void ibmvscsis_aborted_task(struct se_cmd *se_cmd) 3737static void ibmvscsis_aborted_task(struct se_cmd *se_cmd)
3674{ 3738{
3675 /* TBD: What (if anything) should we do here? */ 3739 pr_debug("ibmvscsis_aborted_task %p task_tag: %llu\n",
3676 pr_debug("ibmvscsis_aborted_task %p\n", se_cmd); 3740 se_cmd, se_cmd->tag);
3677} 3741}
3678 3742
3679static struct se_wwn *ibmvscsis_make_tport(struct target_fabric_configfs *tf, 3743static struct se_wwn *ibmvscsis_make_tport(struct target_fabric_configfs *tf,
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
index 65c6189885ab..b4391a8de456 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
@@ -168,10 +168,12 @@ struct ibmvscsis_cmd {
168 struct iu_rsp rsp; 168 struct iu_rsp rsp;
169 struct work_struct work; 169 struct work_struct work;
170 struct scsi_info *adapter; 170 struct scsi_info *adapter;
171 struct ibmvscsis_cmd *abort_cmd;
171 /* Sense buffer that will be mapped into outgoing status */ 172 /* Sense buffer that will be mapped into outgoing status */
172 unsigned char sense_buf[TRANSPORT_SENSE_BUFFER]; 173 unsigned char sense_buf[TRANSPORT_SENSE_BUFFER];
173 u64 init_time; 174 u64 init_time;
174#define CMD_FAST_FAIL BIT(0) 175#define CMD_FAST_FAIL BIT(0)
176#define DELAY_SEND BIT(1)
175 u32 flags; 177 u32 flags;
176 char type; 178 char type;
177}; 179};