]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Jun 2014 00:13:10 +0000 (17:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Jun 2014 00:13:10 +0000 (17:13 -0700)
added patches:
iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch
libiscsi-iser-adjust-data_length-to-include-protection-information.patch
scsi_cmnd-introduce-scsi_transfer_length-helper.patch
target-iscsi-fix-sendtargets-response-pdu-for-iser-transport.patch
target-iser-fix-a-wrong-dereference-in-case-discovery-session-is-over-iser.patch
target-iser-gracefully-reject-t10-pi-enabled-connect-request-if-not-supported.patch
target-iser-improve-cm-events-handling.patch
target-iser-wait-for-proper-cleanup-before-unloading.patch
target-report-correct-response-length-for-some-commands.patch
target-sbc-loopback-adjust-command-data-length-in-case-pi-exists-on-the-wire.patch
target-set-cmd_t_active-bit-for-task-management-requests.patch
target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch

13 files changed:
queue-3.15/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch [new file with mode: 0644]
queue-3.15/libiscsi-iser-adjust-data_length-to-include-protection-information.patch [new file with mode: 0644]
queue-3.15/scsi_cmnd-introduce-scsi_transfer_length-helper.patch [new file with mode: 0644]
queue-3.15/series
queue-3.15/target-iscsi-fix-sendtargets-response-pdu-for-iser-transport.patch [new file with mode: 0644]
queue-3.15/target-iser-fix-a-wrong-dereference-in-case-discovery-session-is-over-iser.patch [new file with mode: 0644]
queue-3.15/target-iser-gracefully-reject-t10-pi-enabled-connect-request-if-not-supported.patch [new file with mode: 0644]
queue-3.15/target-iser-improve-cm-events-handling.patch [new file with mode: 0644]
queue-3.15/target-iser-wait-for-proper-cleanup-before-unloading.patch [new file with mode: 0644]
queue-3.15/target-report-correct-response-length-for-some-commands.patch [new file with mode: 0644]
queue-3.15/target-sbc-loopback-adjust-command-data-length-in-case-pi-exists-on-the-wire.patch [new file with mode: 0644]
queue-3.15/target-set-cmd_t_active-bit-for-task-management-requests.patch [new file with mode: 0644]
queue-3.15/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch [new file with mode: 0644]

diff --git a/queue-3.15/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch b/queue-3.15/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch
new file mode 100644 (file)
index 0000000..0b66930
--- /dev/null
@@ -0,0 +1,48 @@
+From bbc050488525e1ab1194c27355f63c66814385b8 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Tue, 10 Jun 2014 04:03:54 +0000
+Subject: iscsi-target: Fix ABORT_TASK + connection reset iscsi_queue_req memory leak
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit bbc050488525e1ab1194c27355f63c66814385b8 upstream.
+
+This patch fixes a iscsi_queue_req memory leak when ABORT_TASK response
+has been queued by TFO->queue_tm_rsp() -> lio_queue_tm_rsp() after a
+long standing I/O completes, but the connection has already reset and
+waiting for cleanup to complete in iscsit_release_commands_from_conn()
+-> transport_generic_free_cmd() -> transport_wait_for_tasks() code.
+
+It moves iscsit_free_queue_reqs_for_conn() after the per-connection command
+list has been released, so that the associated se_cmd tag can be completed +
+released by target-core before freeing any remaining iscsi_queue_req memory
+for the connection generated by lio_queue_tm_rsp().
+
+Cc: Thomas Glanzmann <thomas@glanzmann.de>
+Cc: Charalampos Pournaris <charpour@gmail.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -4234,8 +4234,6 @@ int iscsit_close_connection(
+       if (conn->conn_transport->iscsit_wait_conn)
+               conn->conn_transport->iscsit_wait_conn(conn);
+-      iscsit_free_queue_reqs_for_conn(conn);
+-
+       /*
+        * During Connection recovery drop unacknowledged out of order
+        * commands for this connection, and prepare the other commands
+@@ -4252,6 +4250,7 @@ int iscsit_close_connection(
+               iscsit_clear_ooo_cmdsns_for_conn(conn);
+               iscsit_release_commands_from_conn(conn);
+       }
++      iscsit_free_queue_reqs_for_conn(conn);
+       /*
+        * Handle decrementing session or connection usage count if
diff --git a/queue-3.15/libiscsi-iser-adjust-data_length-to-include-protection-information.patch b/queue-3.15/libiscsi-iser-adjust-data_length-to-include-protection-information.patch
new file mode 100644 (file)
index 0000000..e9a3a9d
--- /dev/null
@@ -0,0 +1,170 @@
+From d77e65350f2d82dfa0557707d505711f5a43c8fd Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Wed, 11 Jun 2014 12:09:58 +0300
+Subject: libiscsi, iser: Adjust data_length to include protection information
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit d77e65350f2d82dfa0557707d505711f5a43c8fd upstream.
+
+In case protection information exists over the wire
+iscsi header data length is required to include it.
+Use protection information aware scsi helpers to set
+the correct transfer length.
+
+In order to avoid breakage, remove iser transfer length
+checks for each task as they are not always true and
+somewhat redundant anyway.
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
+Acked-by: Mike Christie <michaelc@cs.wisc.edu>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iser_initiator.c |   34 +++++++--------------------
+ drivers/scsi/libiscsi.c                      |   18 +++++++-------
+ 2 files changed, 19 insertions(+), 33 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -41,11 +41,11 @@
+ #include "iscsi_iser.h"
+ /* Register user buffer memory and initialize passive rdma
+- *  dto descriptor. Total data size is stored in
+- *  iser_task->data[ISER_DIR_IN].data_len
++ *  dto descriptor. Data size is stored in
++ *  task->data[ISER_DIR_IN].data_len, Protection size
++ *  os stored in task->prot[ISER_DIR_IN].data_len
+  */
+-static int iser_prepare_read_cmd(struct iscsi_task *task,
+-                               unsigned int edtl)
++static int iser_prepare_read_cmd(struct iscsi_task *task)
+ {
+       struct iscsi_iser_task *iser_task = task->dd_data;
+@@ -73,14 +73,6 @@ static int iser_prepare_read_cmd(struct
+                       return err;
+       }
+-      if (edtl > iser_task->data[ISER_DIR_IN].data_len) {
+-              iser_err("Total data length: %ld, less than EDTL: "
+-                       "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
+-                       iser_task->data[ISER_DIR_IN].data_len, edtl,
+-                       task->itt, iser_task->ib_conn);
+-              return -EINVAL;
+-      }
+-
+       err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_IN);
+       if (err) {
+               iser_err("Failed to set up Data-IN RDMA\n");
+@@ -100,8 +92,9 @@ static int iser_prepare_read_cmd(struct
+ }
+ /* Register user buffer memory and initialize passive rdma
+- *  dto descriptor. Total data size is stored in
+- *  task->data[ISER_DIR_OUT].data_len
++ *  dto descriptor. Data size is stored in
++ *  task->data[ISER_DIR_OUT].data_len, Protection size
++ *  is stored at task->prot[ISER_DIR_OUT].data_len
+  */
+ static int
+ iser_prepare_write_cmd(struct iscsi_task *task,
+@@ -135,14 +128,6 @@ iser_prepare_write_cmd(struct iscsi_task
+                       return err;
+       }
+-      if (edtl > iser_task->data[ISER_DIR_OUT].data_len) {
+-              iser_err("Total data length: %ld, less than EDTL: %d, "
+-                       "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
+-                       iser_task->data[ISER_DIR_OUT].data_len,
+-                       edtl, task->itt, task->conn);
+-              return -EINVAL;
+-      }
+-
+       err = device->iser_reg_rdma_mem(iser_task, ISER_DIR_OUT);
+       if (err != 0) {
+               iser_err("Failed to register write cmd RDMA mem\n");
+@@ -417,11 +402,12 @@ int iser_send_command(struct iscsi_conn
+       if (scsi_prot_sg_count(sc)) {
+               prot_buf->buf  = scsi_prot_sglist(sc);
+               prot_buf->size = scsi_prot_sg_count(sc);
+-              prot_buf->data_len = sc->prot_sdb->length;
++              prot_buf->data_len = data_buf->data_len >>
++                                   ilog2(sc->device->sector_size) * 8;
+       }
+       if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+-              err = iser_prepare_read_cmd(task, edtl);
++              err = iser_prepare_read_cmd(task);
+               if (err)
+                       goto send_command_error;
+       }
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -338,7 +338,7 @@ static int iscsi_prep_scsi_cmd_pdu(struc
+       struct iscsi_session *session = conn->session;
+       struct scsi_cmnd *sc = task->sc;
+       struct iscsi_scsi_req *hdr;
+-      unsigned hdrlength, cmd_len;
++      unsigned hdrlength, cmd_len, transfer_length;
+       itt_t itt;
+       int rc;
+@@ -391,11 +391,11 @@ static int iscsi_prep_scsi_cmd_pdu(struc
+       if (scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
+               task->protected = true;
++      transfer_length = scsi_transfer_length(sc);
++      hdr->data_length = cpu_to_be32(transfer_length);
+       if (sc->sc_data_direction == DMA_TO_DEVICE) {
+-              unsigned out_len = scsi_out(sc)->length;
+               struct iscsi_r2t_info *r2t = &task->unsol_r2t;
+-              hdr->data_length = cpu_to_be32(out_len);
+               hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+               /*
+                * Write counters:
+@@ -414,18 +414,19 @@ static int iscsi_prep_scsi_cmd_pdu(struc
+               memset(r2t, 0, sizeof(*r2t));
+               if (session->imm_data_en) {
+-                      if (out_len >= session->first_burst)
++                      if (transfer_length >= session->first_burst)
+                               task->imm_count = min(session->first_burst,
+                                                       conn->max_xmit_dlength);
+                       else
+-                              task->imm_count = min(out_len,
+-                                                      conn->max_xmit_dlength);
++                              task->imm_count = min(transfer_length,
++                                                    conn->max_xmit_dlength);
+                       hton24(hdr->dlength, task->imm_count);
+               } else
+                       zero_data(hdr->dlength);
+               if (!session->initial_r2t_en) {
+-                      r2t->data_length = min(session->first_burst, out_len) -
++                      r2t->data_length = min(session->first_burst,
++                                             transfer_length) -
+                                              task->imm_count;
+                       r2t->data_offset = task->imm_count;
+                       r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+@@ -438,7 +439,6 @@ static int iscsi_prep_scsi_cmd_pdu(struc
+       } else {
+               hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+               zero_data(hdr->dlength);
+-              hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+               if (sc->sc_data_direction == DMA_FROM_DEVICE)
+                       hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -466,7 +466,7 @@ static int iscsi_prep_scsi_cmd_pdu(struc
+                         scsi_bidi_cmnd(sc) ? "bidirectional" :
+                         sc->sc_data_direction == DMA_TO_DEVICE ?
+                         "write" : "read", conn->id, sc, sc->cmnd[0],
+-                        task->itt, scsi_bufflen(sc),
++                        task->itt, transfer_length,
+                         scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+                         session->cmdsn,
+                         session->max_cmdsn - session->exp_cmdsn + 1);
diff --git a/queue-3.15/scsi_cmnd-introduce-scsi_transfer_length-helper.patch b/queue-3.15/scsi_cmnd-introduce-scsi_transfer_length-helper.patch
new file mode 100644 (file)
index 0000000..ae02fcf
--- /dev/null
@@ -0,0 +1,56 @@
+From 8846bab180fa2bcfe02d4ba5288fbaba12c8f4f3 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Wed, 11 Jun 2014 12:09:57 +0300
+Subject: scsi_cmnd: Introduce scsi_transfer_length helper
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 8846bab180fa2bcfe02d4ba5288fbaba12c8f4f3 upstream.
+
+In case protection information exists on the wire
+scsi transports should include it in the transfer
+byte count (even if protection information does not
+exist in the host memory space). This helper will
+compute the total transfer length from the scsi
+command data length and protection attributes.
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/scsi/scsi_cmnd.h |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/include/scsi/scsi_cmnd.h
++++ b/include/scsi/scsi_cmnd.h
+@@ -7,6 +7,7 @@
+ #include <linux/types.h>
+ #include <linux/timer.h>
+ #include <linux/scatterlist.h>
++#include <scsi/scsi_device.h>
+ struct Scsi_Host;
+ struct scsi_device;
+@@ -306,4 +307,20 @@ static inline void set_driver_byte(struc
+       cmd->result = (cmd->result & 0x00ffffff) | (status << 24);
+ }
++static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd)
++{
++      unsigned int xfer_len = blk_rq_bytes(scmd->request);
++      unsigned int prot_op = scsi_get_prot_op(scmd);
++      unsigned int sector_size = scmd->device->sector_size;
++
++      switch (prot_op) {
++      case SCSI_PROT_NORMAL:
++      case SCSI_PROT_WRITE_STRIP:
++      case SCSI_PROT_READ_INSERT:
++              return xfer_len;
++      }
++
++      return xfer_len + (xfer_len >> ilog2(sector_size)) * 8;
++}
++
+ #endif /* _SCSI_SCSI_CMND_H */
index 1c5833b0736dcaf69cb2e99cb26f2f7b7fb7a7fb..bc8e595c816d079050f1536c45e91c8118bbf2ea 100644 (file)
@@ -86,3 +86,15 @@ bluetooth-fix-requiring-smp-mitm-for-outgoing-connections.patch
 bluetooth-fix-missing-check-for-fips-security-level.patch
 target-iser-bail-from-accept_np-if-np_thread-is-trying-to-close.patch
 target-iser-fix-hangs-in-connection-teardown.patch
+target-iser-improve-cm-events-handling.patch
+target-iser-wait-for-proper-cleanup-before-unloading.patch
+target-iser-gracefully-reject-t10-pi-enabled-connect-request-if-not-supported.patch
+target-set-cmd_t_active-bit-for-task-management-requests.patch
+target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch
+iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch
+target-iser-fix-a-wrong-dereference-in-case-discovery-session-is-over-iser.patch
+target-iscsi-fix-sendtargets-response-pdu-for-iser-transport.patch
+target-report-correct-response-length-for-some-commands.patch
+scsi_cmnd-introduce-scsi_transfer_length-helper.patch
+libiscsi-iser-adjust-data_length-to-include-protection-information.patch
+target-sbc-loopback-adjust-command-data-length-in-case-pi-exists-on-the-wire.patch
diff --git a/queue-3.15/target-iscsi-fix-sendtargets-response-pdu-for-iser-transport.patch b/queue-3.15/target-iscsi-fix-sendtargets-response-pdu-for-iser-transport.patch
new file mode 100644 (file)
index 0000000..72dd785
--- /dev/null
@@ -0,0 +1,98 @@
+From 22c7aaa57e80853b4904a46c18f97db0036a3b97 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Tue, 10 Jun 2014 18:27:59 +0300
+Subject: Target/iscsi: Fix sendtargets response pdu for iser transport
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 22c7aaa57e80853b4904a46c18f97db0036a3b97 upstream.
+
+In case the transport is iser we should not include the
+iscsi target info in the sendtargets text response pdu.
+This causes sendtargets response to include the target
+info twice.
+
+Modify iscsit_build_sendtargets_response to filter
+transport types that don't match.
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Reported-by: Slava Shwartsman <valyushash@gmail.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/isert/ib_isert.c |    2 +-
+ drivers/target/iscsi/iscsi_target.c     |   14 ++++++++++----
+ include/target/iscsi/iscsi_transport.h  |    3 ++-
+ 3 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -2320,7 +2320,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd
+       int rc;
+       isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
+-      rc = iscsit_build_text_rsp(cmd, conn, hdr);
++      rc = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_INFINIBAND);
+       if (rc < 0)
+               return rc;
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -3390,7 +3390,9 @@ static bool iscsit_check_inaddr_any(stru
+ #define SENDTARGETS_BUF_LIMIT 32768U
+-static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
++static int
++iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
++                                enum iscsit_transport_type network_transport)
+ {
+       char *payload = NULL;
+       struct iscsi_conn *conn = cmd->conn;
+@@ -3467,6 +3469,9 @@ static int iscsit_build_sendtargets_resp
+                               struct iscsi_np *np = tpg_np->tpg_np;
+                               bool inaddr_any = iscsit_check_inaddr_any(np);
++                              if (np->np_network_transport != network_transport)
++                                      continue;
++
+                               if (!target_name_printed) {
+                                       len = sprintf(buf, "TargetName=%s",
+                                                     tiqn->tiqn);
+@@ -3520,11 +3525,12 @@ eob:
+ int
+ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+-                    struct iscsi_text_rsp *hdr)
++                    struct iscsi_text_rsp *hdr,
++                    enum iscsit_transport_type network_transport)
+ {
+       int text_length, padding;
+-      text_length = iscsit_build_sendtargets_response(cmd);
++      text_length = iscsit_build_sendtargets_response(cmd, network_transport);
+       if (text_length < 0)
+               return text_length;
+@@ -3562,7 +3568,7 @@ static int iscsit_send_text_rsp(
+       u32 tx_size = 0;
+       int text_length, iov_count = 0, rc;
+-      rc = iscsit_build_text_rsp(cmd, conn, hdr);
++      rc = iscsit_build_text_rsp(cmd, conn, hdr, ISCSI_TCP);
+       if (rc < 0)
+               return rc;
+--- a/include/target/iscsi/iscsi_transport.h
++++ b/include/target/iscsi/iscsi_transport.h
+@@ -70,7 +70,8 @@ extern void iscsit_build_nopin_rsp(struc
+ extern void iscsit_build_task_mgt_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+                               struct iscsi_tm_rsp *);
+ extern int iscsit_build_text_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+-                              struct iscsi_text_rsp *);
++                              struct iscsi_text_rsp *,
++                              enum iscsit_transport_type);
+ extern void iscsit_build_reject(struct iscsi_cmd *, struct iscsi_conn *,
+                               struct iscsi_reject *);
+ extern int iscsit_build_logout_rsp(struct iscsi_cmd *, struct iscsi_conn *,
diff --git a/queue-3.15/target-iser-fix-a-wrong-dereference-in-case-discovery-session-is-over-iser.patch b/queue-3.15/target-iser-fix-a-wrong-dereference-in-case-discovery-session-is-over-iser.patch
new file mode 100644 (file)
index 0000000..b08201a
--- /dev/null
@@ -0,0 +1,36 @@
+From e0546fc1ba66c90cb38a5764357366267d3e58e4 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Tue, 10 Jun 2014 13:41:41 +0300
+Subject: Target/iser: Fix a wrong dereference in case discovery session is over iser
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit e0546fc1ba66c90cb38a5764357366267d3e58e4 upstream.
+
+In case the discovery session is carried over iser, we can't
+access the assumed network portal since the default portal is
+used. In this case we don't really need to allocate the fastreg
+pool, just prepare to the text pdu that will follow.
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Reported-by: Alex Tabachnik <alext@mellanox.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/isert/ib_isert.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -1053,7 +1053,9 @@ isert_put_login_tx(struct iscsi_conn *co
+       }
+       if (!login->login_failed) {
+               if (login->login_complete) {
+-                      if (isert_conn->conn_device->use_fastreg) {
++                      if (!conn->sess->sess_ops->SessionType &&
++                          isert_conn->conn_device->use_fastreg) {
++                              /* Normal Session and fastreg is used */
+                               u8 pi_support = login->np->tpg_np->tpg->tpg_attrib.t10_pi;
+                               ret = isert_conn_create_fastreg_pool(isert_conn,
diff --git a/queue-3.15/target-iser-gracefully-reject-t10-pi-enabled-connect-request-if-not-supported.patch b/queue-3.15/target-iser-gracefully-reject-t10-pi-enabled-connect-request-if-not-supported.patch
new file mode 100644 (file)
index 0000000..eb54f78
--- /dev/null
@@ -0,0 +1,35 @@
+From 5f80ff8eccba50832dcc640ac89add4c7fced963 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Tue, 20 May 2014 13:28:11 +0300
+Subject: Target/iser: Gracefully reject T10-PI enabled connect request if not supported
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 5f80ff8eccba50832dcc640ac89add4c7fced963 upstream.
+
+In case user chose to set T10-PI enable on the target while
+the IB device does not support it, gracefully reject the request.
+
+Reported-by: Slava Shwartsman <valyushash@gmail.com>
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/isert/ib_isert.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -663,8 +663,9 @@ isert_connect_request(struct rdma_cm_id
+       pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
+       if (pi_support && !device->pi_capable) {
+-              pr_err("Protection information requested but not supported\n");
+-              ret = -EINVAL;
++              pr_err("Protection information requested but not supported, "
++                     "rejecting connect request\n");
++              ret = rdma_reject(cma_id, NULL, 0);
+               goto out_mr;
+       }
diff --git a/queue-3.15/target-iser-improve-cm-events-handling.patch b/queue-3.15/target-iser-improve-cm-events-handling.patch
new file mode 100644 (file)
index 0000000..c12a155
--- /dev/null
@@ -0,0 +1,113 @@
+From 88c4015fda6d014392f76d3b1688347950d7a12d Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Mon, 19 May 2014 17:44:24 +0300
+Subject: Target/iser: Improve cm events handling
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 88c4015fda6d014392f76d3b1688347950d7a12d upstream.
+
+There are 4 RDMA_CM events that all basically mean that
+the user should teardown the IB connection:
+- DISCONNECTED
+- ADDR_CHANGE
+- DEVICE_REMOVAL
+- TIMEWAIT_EXIT
+
+Only in DISCONNECTED/ADDR_CHANGE it makes sense to
+call rdma_disconnect (send DREQ/DREP to our initiator).
+So we keep the same teardown handler for all of them
+but only indicate calling rdma_disconnect for the relevant
+events.
+
+This patch also removes redundant debug prints for each single
+event.
+
+v2 changes:
+ - Call isert_disconnected_handler() for DEVICE_REMOVAL (Or + Sag)
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/isert/ib_isert.c |   26 ++++++++++++++------------
+ drivers/infiniband/ulp/isert/ib_isert.h |    1 +
+ 2 files changed, 15 insertions(+), 12 deletions(-)
+
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -788,8 +788,10 @@ isert_disconnect_work(struct work_struct
+               return;
+       }
+-      /* Send DREQ/DREP towards our initiator */
+-      rdma_disconnect(isert_conn->conn_cm_id);
++      if (isert_conn->disconnect) {
++              /* Send DREQ/DREP towards our initiator */
++              rdma_disconnect(isert_conn->conn_cm_id);
++      }
+       mutex_unlock(&isert_conn->conn_mutex);
+@@ -799,10 +801,11 @@ wake_up:
+ }
+ static void
+-isert_disconnected_handler(struct rdma_cm_id *cma_id)
++isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect)
+ {
+       struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context;
++      isert_conn->disconnect = disconnect;
+       INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work);
+       schedule_work(&isert_conn->conn_logout_work);
+ }
+@@ -811,29 +814,28 @@ static int
+ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+ {
+       int ret = 0;
++      bool disconnect = false;
+       pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n",
+                event->event, event->status, cma_id->context, cma_id);
+       switch (event->event) {
+       case RDMA_CM_EVENT_CONNECT_REQUEST:
+-              pr_debug("RDMA_CM_EVENT_CONNECT_REQUEST: >>>>>>>>>>>>>>>\n");
+               ret = isert_connect_request(cma_id, event);
+               break;
+       case RDMA_CM_EVENT_ESTABLISHED:
+-              pr_debug("RDMA_CM_EVENT_ESTABLISHED >>>>>>>>>>>>>>\n");
+               isert_connected_handler(cma_id);
+               break;
+-      case RDMA_CM_EVENT_DISCONNECTED:
+-              pr_debug("RDMA_CM_EVENT_DISCONNECTED: >>>>>>>>>>>>>>\n");
+-              isert_disconnected_handler(cma_id);
+-              break;
+-      case RDMA_CM_EVENT_DEVICE_REMOVAL:
+-      case RDMA_CM_EVENT_ADDR_CHANGE:
++      case RDMA_CM_EVENT_ADDR_CHANGE:    /* FALLTHRU */
++      case RDMA_CM_EVENT_DISCONNECTED:   /* FALLTHRU */
++      case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
++              disconnect = true;
++      case RDMA_CM_EVENT_TIMEWAIT_EXIT:  /* FALLTHRU */
++              isert_disconnected_handler(cma_id, disconnect);
+               break;
+       case RDMA_CM_EVENT_CONNECT_ERROR:
+       default:
+-              pr_err("Unknown RDMA CMA event: %d\n", event->event);
++              pr_err("Unhandled RDMA CMA event: %d\n", event->event);
+               break;
+       }
+--- a/drivers/infiniband/ulp/isert/ib_isert.h
++++ b/drivers/infiniband/ulp/isert/ib_isert.h
+@@ -150,6 +150,7 @@ struct isert_conn {
+ #define ISERT_COMP_BATCH_COUNT        8
+       int                     conn_comp_batch;
+       struct llist_head       conn_comp_llist;
++      bool                    disconnect;
+ };
+ #define ISERT_MAX_CQ 64
diff --git a/queue-3.15/target-iser-wait-for-proper-cleanup-before-unloading.patch b/queue-3.15/target-iser-wait-for-proper-cleanup-before-unloading.patch
new file mode 100644 (file)
index 0000000..36e36bd
--- /dev/null
@@ -0,0 +1,31 @@
+From f5ebec9629cf78eeeea4b8258882a9f439ab2404 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Mon, 19 May 2014 17:44:25 +0300
+Subject: Target/iser: Wait for proper cleanup before unloading
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit f5ebec9629cf78eeeea4b8258882a9f439ab2404 upstream.
+
+disconnected_handler works are scheduled on system_wq.
+When attempting to unload, first make sure all works
+have cleaned up.
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/isert/ib_isert.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -3289,6 +3289,7 @@ destroy_rx_wq:
+ static void __exit isert_exit(void)
+ {
++      flush_scheduled_work();
+       destroy_workqueue(isert_comp_wq);
+       destroy_workqueue(isert_rx_wq);
+       iscsit_unregister_transport(&iser_target_transport);
diff --git a/queue-3.15/target-report-correct-response-length-for-some-commands.patch b/queue-3.15/target-report-correct-response-length-for-some-commands.patch
new file mode 100644 (file)
index 0000000..a4693a9
--- /dev/null
@@ -0,0 +1,145 @@
+From 2426bd456a61407388b6e61fc5f98dbcbebc50e2 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+Date: Tue, 10 Jun 2014 11:07:47 -0700
+Subject: target: Report correct response length for some commands
+
+From: Roland Dreier <roland@purestorage.com>
+
+commit 2426bd456a61407388b6e61fc5f98dbcbebc50e2 upstream.
+
+When an initiator sends an allocation length bigger than what its
+command consumes, the target should only return the actual response data
+and set the residual length to the unused part of the allocation length.
+
+Add a helper function that command handlers (INQUIRY, READ CAPACITY,
+etc) can use to do this correctly, and use this code to get the correct
+residual for commands that don't use the full initiator allocation in the
+handlers for READ CAPACITY, READ CAPACITY(16), INQUIRY, MODE SENSE and
+REPORT LUNS.
+
+This addresses a handful of failures as reported by Christophe with
+the Windows Certification Kit:
+
+  http://permalink.gmane.org/gmane.linux.scsi.target.devel/6515
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Tested-by: Christophe Vu-Brugier <cvubrugier@yahoo.fr>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_sbc.c       |    4 ++--
+ drivers/target/target_core_spc.c       |    9 ++++++---
+ drivers/target/target_core_transport.c |   17 +++++++++++++++++
+ include/target/target_core_backend.h   |    1 +
+ 4 files changed, 26 insertions(+), 5 deletions(-)
+
+--- a/drivers/target/target_core_sbc.c
++++ b/drivers/target/target_core_sbc.c
+@@ -81,7 +81,7 @@ sbc_emulate_readcapacity(struct se_cmd *
+               transport_kunmap_data_sg(cmd);
+       }
+-      target_complete_cmd(cmd, GOOD);
++      target_complete_cmd_with_length(cmd, GOOD, 8);
+       return 0;
+ }
+@@ -137,7 +137,7 @@ sbc_emulate_readcapacity_16(struct se_cm
+               transport_kunmap_data_sg(cmd);
+       }
+-      target_complete_cmd(cmd, GOOD);
++      target_complete_cmd_with_length(cmd, GOOD, 32);
+       return 0;
+ }
+--- a/drivers/target/target_core_spc.c
++++ b/drivers/target/target_core_spc.c
+@@ -721,6 +721,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
+       unsigned char *buf;
+       sense_reason_t ret;
+       int p;
++      int len = 0;
+       buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
+       if (!buf) {
+@@ -742,6 +743,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
+               }
+               ret = spc_emulate_inquiry_std(cmd, buf);
++              len = buf[4] + 5;
+               goto out;
+       }
+@@ -749,6 +751,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
+               if (cdb[2] == evpd_handlers[p].page) {
+                       buf[1] = cdb[2];
+                       ret = evpd_handlers[p].emulate(cmd, buf);
++                      len = get_unaligned_be16(&buf[2]) + 4;
+                       goto out;
+               }
+       }
+@@ -765,7 +768,7 @@ out:
+       kfree(buf);
+       if (!ret)
+-              target_complete_cmd(cmd, GOOD);
++              target_complete_cmd_with_length(cmd, GOOD, len);
+       return ret;
+ }
+@@ -1103,7 +1106,7 @@ set_length:
+               transport_kunmap_data_sg(cmd);
+       }
+-      target_complete_cmd(cmd, GOOD);
++      target_complete_cmd_with_length(cmd, GOOD, length);
+       return 0;
+ }
+@@ -1279,7 +1282,7 @@ done:
+       buf[3] = (lun_count & 0xff);
+       transport_kunmap_data_sg(cmd);
+-      target_complete_cmd(cmd, GOOD);
++      target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
+       return 0;
+ }
+ EXPORT_SYMBOL(spc_emulate_report_luns);
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -703,6 +703,23 @@ void target_complete_cmd(struct se_cmd *
+ }
+ EXPORT_SYMBOL(target_complete_cmd);
++void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
++{
++      if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
++              if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
++                      cmd->residual_count += cmd->data_length - length;
++              } else {
++                      cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
++                      cmd->residual_count = cmd->data_length - length;
++              }
++
++              cmd->data_length = length;
++      }
++
++      target_complete_cmd(cmd, scsi_status);
++}
++EXPORT_SYMBOL(target_complete_cmd_with_length);
++
+ static void target_add_to_state_list(struct se_cmd *cmd)
+ {
+       struct se_device *dev = cmd->se_dev;
+--- a/include/target/target_core_backend.h
++++ b/include/target/target_core_backend.h
+@@ -59,6 +59,7 @@ int  transport_subsystem_register(struct
+ void  transport_subsystem_release(struct se_subsystem_api *);
+ void  target_complete_cmd(struct se_cmd *, u8);
++void  target_complete_cmd_with_length(struct se_cmd *, u8, int);
+ sense_reason_t        spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
+ sense_reason_t        spc_emulate_report_luns(struct se_cmd *cmd);
diff --git a/queue-3.15/target-sbc-loopback-adjust-command-data-length-in-case-pi-exists-on-the-wire.patch b/queue-3.15/target-sbc-loopback-adjust-command-data-length-in-case-pi-exists-on-the-wire.patch
new file mode 100644 (file)
index 0000000..ebfd46f
--- /dev/null
@@ -0,0 +1,87 @@
+From e2a4f55c6498b59a17a85a1bb6db122a993ffe02 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Wed, 11 Jun 2014 12:09:59 +0300
+Subject: TARGET/sbc,loopback: Adjust command data length in case pi exists on the wire
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit e2a4f55c6498b59a17a85a1bb6db122a993ffe02 upstream.
+
+In various areas of the code, it is assumed that
+se_cmd->data_length describes pure data. In case
+that protection information exists over the wire
+(protect bits is are on) the target core re-calculates
+the data length from the CDB and the backed device
+block size (instead of each transport peeking in the cdb).
+
+Modify loopback device to include protection information
+in the transferred data length (like other scsi transports).
+
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/loopback/tcm_loop.c |   15 ++++++++++++---
+ drivers/target/target_core_sbc.c   |   15 +++++++++++++--
+ 2 files changed, 25 insertions(+), 5 deletions(-)
+
+--- a/drivers/target/loopback/tcm_loop.c
++++ b/drivers/target/loopback/tcm_loop.c
+@@ -179,7 +179,7 @@ static void tcm_loop_submission_work(str
+       struct tcm_loop_hba *tl_hba;
+       struct tcm_loop_tpg *tl_tpg;
+       struct scatterlist *sgl_bidi = NULL;
+-      u32 sgl_bidi_count = 0;
++      u32 sgl_bidi_count = 0, transfer_length;
+       int rc;
+       tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
+@@ -213,12 +213,21 @@ static void tcm_loop_submission_work(str
+       }
+-      if (!scsi_prot_sg_count(sc) && scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
++      transfer_length = scsi_transfer_length(sc);
++      if (!scsi_prot_sg_count(sc) &&
++          scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) {
+               se_cmd->prot_pto = true;
++              /*
++               * loopback transport doesn't support
++               * WRITE_GENERATE, READ_STRIP protection
++               * information operations, go ahead unprotected.
++               */
++              transfer_length = scsi_bufflen(sc);
++      }
+       rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
+                       &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
+-                      scsi_bufflen(sc), tcm_loop_sam_attr(sc),
++                      transfer_length, tcm_loop_sam_attr(sc),
+                       sc->sc_data_direction, 0,
+                       scsi_sglist(sc), scsi_sg_count(sc),
+                       sgl_bidi, sgl_bidi_count,
+--- a/drivers/target/target_core_sbc.c
++++ b/drivers/target/target_core_sbc.c
+@@ -665,8 +665,19 @@ sbc_check_prot(struct se_device *dev, st
+       cmd->prot_type = dev->dev_attrib.pi_prot_type;
+       cmd->prot_length = dev->prot_length * sectors;
+-      pr_debug("%s: prot_type=%d, prot_length=%d prot_op=%d prot_checks=%d\n",
+-               __func__, cmd->prot_type, cmd->prot_length,
++
++      /**
++       * In case protection information exists over the wire
++       * we modify command data length to describe pure data.
++       * The actual transfer length is data length + protection
++       * length
++       **/
++      if (protect)
++              cmd->data_length = sectors * dev->dev_attrib.block_size;
++
++      pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d "
++               "prot_op=%d prot_checks=%d\n",
++               __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
+                cmd->prot_op, cmd->prot_checks);
+       return true;
diff --git a/queue-3.15/target-set-cmd_t_active-bit-for-task-management-requests.patch b/queue-3.15/target-set-cmd_t_active-bit-for-task-management-requests.patch
new file mode 100644 (file)
index 0000000..e9be61b
--- /dev/null
@@ -0,0 +1,42 @@
+From f15e9cd910c4d9da7de43f2181f362082fc45f0f Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Mon, 9 Jun 2014 23:13:20 +0000
+Subject: target: Set CMD_T_ACTIVE bit for Task Management Requests
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit f15e9cd910c4d9da7de43f2181f362082fc45f0f upstream.
+
+This patch fixes a bug where se_cmd descriptors associated with a
+Task Management Request (TMR) where not setting CMD_T_ACTIVE before
+being dispatched into target_tmr_work() process context.
+
+This is required in order for transport_generic_free_cmd() ->
+transport_wait_for_tasks() to wait on se_cmd->t_transport_stop_comp
+if a session reset event occurs while an ABORT_TASK is outstanding
+waiting for another I/O to complete.
+
+Cc: Thomas Glanzmann <thomas@glanzmann.de>
+Cc: Charalampos Pournaris <charpour@gmail.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_transport.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -2938,6 +2938,12 @@ static void target_tmr_work(struct work_
+ int transport_generic_handle_tmr(
+       struct se_cmd *cmd)
+ {
++      unsigned long flags;
++
++      spin_lock_irqsave(&cmd->t_state_lock, flags);
++      cmd->transport_state |= CMD_T_ACTIVE;
++      spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+       INIT_WORK(&cmd->work, target_tmr_work);
+       queue_work(cmd->se_dev->tmr_wq, &cmd->work);
+       return 0;
diff --git a/queue-3.15/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch b/queue-3.15/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch
new file mode 100644 (file)
index 0000000..57be430
--- /dev/null
@@ -0,0 +1,56 @@
+From a95d6511303b848da45ee27b35018bb58087bdc6 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Mon, 9 Jun 2014 23:36:51 +0000
+Subject: target: Use complete_all for se_cmd->t_transport_stop_comp
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit a95d6511303b848da45ee27b35018bb58087bdc6 upstream.
+
+This patch fixes a bug where multiple waiters on ->t_transport_stop_comp
+occurs due to a concurrent ABORT_TASK and session reset both invoking
+transport_wait_for_tasks(), while waiting for the associated se_cmd
+descriptor backend processing to complete.
+
+For this case, complete_all() should be invoked in order to wake up
+both waiters in core_tmr_abort_task() + transport_generic_free_cmd()
+process contexts.
+
+Cc: Thomas Glanzmann <thomas@glanzmann.de>
+Cc: Charalampos Pournaris <charpour@gmail.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_transport.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -562,7 +562,7 @@ static int transport_cmd_check_stop(stru
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-              complete(&cmd->t_transport_stop_comp);
++              complete_all(&cmd->t_transport_stop_comp);
+               return 1;
+       }
+@@ -687,7 +687,7 @@ void target_complete_cmd(struct se_cmd *
+       if (cmd->transport_state & CMD_T_ABORTED &&
+           cmd->transport_state & CMD_T_STOP) {
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+-              complete(&cmd->t_transport_stop_comp);
++              complete_all(&cmd->t_transport_stop_comp);
+               return;
+       } else if (!success) {
+               INIT_WORK(&cmd->work, target_complete_failure_work);
+@@ -1761,7 +1761,7 @@ void target_execute_cmd(struct se_cmd *c
+                       cmd->se_tfo->get_task_tag(cmd));
+               spin_unlock_irq(&cmd->t_state_lock);
+-              complete(&cmd->t_transport_stop_comp);
++              complete_all(&cmd->t_transport_stop_comp);
+               return;
+       }