Commit a55da8a0 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
 "Here are the outstanding target-pending fixes for v4.9-rc2.

  This includes:

   - Fix v4.1.y+ reference leak regression with concurrent TMR
     ABORT_TASK + session shutdown. (Vaibhav Tandon)

   - Enable tcm_fc w/ SCF_USE_CPUID to avoid host exchange timeouts
     (Hannes)

   - target/user error sense handling fixes. (Andy + MNC + HCH)

   - Fix iscsi-target NOP_OUT error path iscsi_cmd descriptor leak
     (Varun)

   - Two EXTENDED_COPY SCSI status fixes for ESX VAAI (Dinesh Israni +
     Nixon Vincent)

   - Revert a v4.8 residual overflow change, that breaks sg_inq with
     small allocation lengths.

  There are a number of folks stress testing the v4.1.y regression fix
  in their environments, and more folks doing iser-target I/O stress
  testing atop recent v4.x.y code.

  There is also one v4.2.y+ RCU conversion regression related to
  explicit NodeACL configfs changes, that is still being tracked down"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target/tcm_fc: use CPU affinity for responses
  target/tcm_fc: Update debugging statements to match libfc usage
  target/tcm_fc: return detailed error in ft_sess_create()
  target/tcm_fc: print command pointer in debug message
  target: fix potential race window in target_sess_cmd_list_waiting()
  Revert "target: Fix residual overflow handling in target_complete_cmd_with_length"
  target: Don't override EXTENDED_COPY xcopy_pt_cmd SCSI status code
  target: Make EXTENDED_COPY 0xe4 failure return COPY TARGET DEVICE NOT REACHABLE
  target: Re-add missing SCF_ACK_KREF assignment in v4.1.y
  iscsi-target: fix iscsi cmd leak
  iscsi-target: fix spelling mistake "Unsolicitied" -> "Unsolicited"
  target/user: Fix comments to not refer to data ring
  target/user: Return an error if cmd data size is too large
  target/user: Use sense_reason_t in tcmu_queue_cmd_ring
parents e6995f22 1ba0158f
...@@ -1804,6 +1804,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -1804,6 +1804,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
* Otherwise, initiator is not expecting a NOPIN is response. * Otherwise, initiator is not expecting a NOPIN is response.
* Just ignore for now. * Just ignore for now.
*/ */
if (cmd)
iscsit_free_cmd(cmd, false);
return 0; return 0;
} }
EXPORT_SYMBOL(iscsit_process_nop_out); EXPORT_SYMBOL(iscsit_process_nop_out);
...@@ -2982,7 +2986,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, ...@@ -2982,7 +2986,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
" StatSN: 0x%08x, Length %u\n", (nopout_response) ? " StatSN: 0x%08x, Length %u\n", (nopout_response) ?
"Solicitied" : "Unsolicitied", cmd->init_task_tag, "Solicited" : "Unsolicited", cmd->init_task_tag,
cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
} }
EXPORT_SYMBOL(iscsit_build_nopin_rsp); EXPORT_SYMBOL(iscsit_build_nopin_rsp);
......
...@@ -434,7 +434,7 @@ static int iscsi_login_zero_tsih_s2( ...@@ -434,7 +434,7 @@ static int iscsi_login_zero_tsih_s2(
/* /*
* Make MaxRecvDataSegmentLength PAGE_SIZE aligned for * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for
* Immediate Data + Unsolicitied Data-OUT if necessary.. * Immediate Data + Unsolicited Data-OUT if necessary..
*/ */
param = iscsi_find_param_from_key("MaxRecvDataSegmentLength", param = iscsi_find_param_from_key("MaxRecvDataSegmentLength",
conn->param_list); conn->param_list);
...@@ -646,7 +646,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) ...@@ -646,7 +646,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
{ {
struct iscsi_session *sess = conn->sess; struct iscsi_session *sess = conn->sess;
/* /*
* FIXME: Unsolicitied NopIN support for ISER * FIXME: Unsolicited NopIN support for ISER
*/ */
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) if (conn->conn_transport->transport_type == ISCSI_INFINIBAND)
return; return;
......
...@@ -754,15 +754,7 @@ EXPORT_SYMBOL(target_complete_cmd); ...@@ -754,15 +754,7 @@ EXPORT_SYMBOL(target_complete_cmd);
void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
{ {
if (scsi_status != SAM_STAT_GOOD) { if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
return;
}
/*
* Calculate new residual count based upon length of SCSI data
* transferred.
*/
if (length < cmd->data_length) {
if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
cmd->residual_count += cmd->data_length - length; cmd->residual_count += cmd->data_length - length;
} else { } else {
...@@ -771,12 +763,6 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len ...@@ -771,12 +763,6 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len
} }
cmd->data_length = length; cmd->data_length = length;
} else if (length > cmd->data_length) {
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
cmd->residual_count = length - cmd->data_length;
} else {
cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT);
cmd->residual_count = 0;
} }
target_complete_cmd(cmd, scsi_status); target_complete_cmd(cmd, scsi_status);
...@@ -1706,6 +1692,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, ...@@ -1706,6 +1692,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED: case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED: case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED: case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
break; break;
case TCM_OUT_OF_RESOURCES: case TCM_OUT_OF_RESOURCES:
sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
...@@ -2547,8 +2534,12 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) ...@@ -2547,8 +2534,12 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
* fabric acknowledgement that requires two target_put_sess_cmd() * fabric acknowledgement that requires two target_put_sess_cmd()
* invocations before se_cmd descriptor release. * invocations before se_cmd descriptor release.
*/ */
if (ack_kref) if (ack_kref) {
kref_get(&se_cmd->cmd_kref); if (!kref_get_unless_zero(&se_cmd->cmd_kref))
return -EINVAL;
se_cmd->se_cmd_flags |= SCF_ACK_KREF;
}
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
if (se_sess->sess_tearing_down) { if (se_sess->sess_tearing_down) {
...@@ -2627,7 +2618,7 @@ EXPORT_SYMBOL(target_put_sess_cmd); ...@@ -2627,7 +2618,7 @@ EXPORT_SYMBOL(target_put_sess_cmd);
*/ */
void target_sess_cmd_list_set_waiting(struct se_session *se_sess) void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
{ {
struct se_cmd *se_cmd; struct se_cmd *se_cmd, *tmp_cmd;
unsigned long flags; unsigned long flags;
int rc; int rc;
...@@ -2639,14 +2630,16 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) ...@@ -2639,14 +2630,16 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
se_sess->sess_tearing_down = 1; se_sess->sess_tearing_down = 1;
list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) { list_for_each_entry_safe(se_cmd, tmp_cmd,
&se_sess->sess_wait_list, se_cmd_list) {
rc = kref_get_unless_zero(&se_cmd->cmd_kref); rc = kref_get_unless_zero(&se_cmd->cmd_kref);
if (rc) { if (rc) {
se_cmd->cmd_wait_set = 1; se_cmd->cmd_wait_set = 1;
spin_lock(&se_cmd->t_state_lock); spin_lock(&se_cmd->t_state_lock);
se_cmd->transport_state |= CMD_T_FABRIC_STOP; se_cmd->transport_state |= CMD_T_FABRIC_STOP;
spin_unlock(&se_cmd->t_state_lock); spin_unlock(&se_cmd->t_state_lock);
} } else
list_del_init(&se_cmd->se_cmd_list);
} }
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
...@@ -2871,6 +2864,12 @@ static const struct sense_info sense_info_table[] = { ...@@ -2871,6 +2864,12 @@ static const struct sense_info sense_info_table[] = {
.ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
.add_sector_info = true, .add_sector_info = true,
}, },
[TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = {
.key = COPY_ABORTED,
.asc = 0x0d,
.ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */
},
[TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = { [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
/* /*
* Returning ILLEGAL REQUEST would cause immediate IO errors on * Returning ILLEGAL REQUEST would cause immediate IO errors on
......
...@@ -96,7 +96,7 @@ struct tcmu_dev { ...@@ -96,7 +96,7 @@ struct tcmu_dev {
size_t dev_size; size_t dev_size;
u32 cmdr_size; u32 cmdr_size;
u32 cmdr_last_cleaned; u32 cmdr_last_cleaned;
/* Offset of data ring from start of mb */ /* Offset of data area from start of mb */
/* Must add data_off and mb_addr to get the address */ /* Must add data_off and mb_addr to get the address */
size_t data_off; size_t data_off;
size_t data_size; size_t data_size;
...@@ -349,7 +349,7 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap) ...@@ -349,7 +349,7 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap)
/* /*
* We can't queue a command until we have space available on the cmd ring *and* * We can't queue a command until we have space available on the cmd ring *and*
* space available on the data ring. * space available on the data area.
* *
* Called with ring lock held. * Called with ring lock held.
*/ */
...@@ -389,7 +389,8 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d ...@@ -389,7 +389,8 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d
return true; return true;
} }
static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) static sense_reason_t
tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
{ {
struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
struct se_cmd *se_cmd = tcmu_cmd->se_cmd; struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
...@@ -405,7 +406,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ...@@ -405,7 +406,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS);
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
return -EINVAL; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/* /*
* Must be a certain minimum size for response sense info, but * Must be a certain minimum size for response sense info, but
...@@ -432,11 +433,14 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ...@@ -432,11 +433,14 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
data_length += se_cmd->t_bidi_data_sg->length; data_length += se_cmd->t_bidi_data_sg->length;
} }
if ((command_size > (udev->cmdr_size / 2)) if ((command_size > (udev->cmdr_size / 2)) ||
|| data_length > udev->data_size) data_length > udev->data_size) {
pr_warn("TCMU: Request of size %zu/%zu may be too big for %u/%zu " pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu "
"cmd/data ring buffers\n", command_size, data_length, "cmd ring/data area\n", command_size, data_length,
udev->cmdr_size, udev->data_size); udev->cmdr_size, udev->data_size);
spin_unlock_irq(&udev->cmdr_lock);
return TCM_INVALID_CDB_FIELD;
}
while (!is_ring_space_avail(udev, command_size, data_length)) { while (!is_ring_space_avail(udev, command_size, data_length)) {
int ret; int ret;
...@@ -450,7 +454,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ...@@ -450,7 +454,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
finish_wait(&udev->wait_cmdr, &__wait); finish_wait(&udev->wait_cmdr, &__wait);
if (!ret) { if (!ret) {
pr_warn("tcmu: command timed out\n"); pr_warn("tcmu: command timed out\n");
return -ETIMEDOUT; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
spin_lock_irq(&udev->cmdr_lock); spin_lock_irq(&udev->cmdr_lock);
...@@ -487,9 +491,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ...@@ -487,9 +491,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS); bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS);
/* /* Handle allocating space from the data area */
* Fix up iovecs, and handle if allocation in data ring wrapped.
*/
iov = &entry->req.iov[0]; iov = &entry->req.iov[0];
iov_cnt = 0; iov_cnt = 0;
copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE
...@@ -526,10 +528,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ...@@ -526,10 +528,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
mod_timer(&udev->timeout, mod_timer(&udev->timeout,
round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT))); round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT)));
return 0; return TCM_NO_SENSE;
} }
static int tcmu_queue_cmd(struct se_cmd *se_cmd) static sense_reason_t
tcmu_queue_cmd(struct se_cmd *se_cmd)
{ {
struct se_device *se_dev = se_cmd->se_dev; struct se_device *se_dev = se_cmd->se_dev;
struct tcmu_dev *udev = TCMU_DEV(se_dev); struct tcmu_dev *udev = TCMU_DEV(se_dev);
...@@ -538,10 +541,10 @@ static int tcmu_queue_cmd(struct se_cmd *se_cmd) ...@@ -538,10 +541,10 @@ static int tcmu_queue_cmd(struct se_cmd *se_cmd)
tcmu_cmd = tcmu_alloc_cmd(se_cmd); tcmu_cmd = tcmu_alloc_cmd(se_cmd);
if (!tcmu_cmd) if (!tcmu_cmd)
return -ENOMEM; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
ret = tcmu_queue_cmd_ring(tcmu_cmd); ret = tcmu_queue_cmd_ring(tcmu_cmd);
if (ret < 0) { if (ret != TCM_NO_SENSE) {
pr_err("TCMU: Could not queue command\n"); pr_err("TCMU: Could not queue command\n");
spin_lock_irq(&udev->commands_lock); spin_lock_irq(&udev->commands_lock);
idr_remove(&udev->commands, tcmu_cmd->cmd_id); idr_remove(&udev->commands, tcmu_cmd->cmd_id);
...@@ -561,7 +564,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry * ...@@ -561,7 +564,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
/* /*
* cmd has been completed already from timeout, just reclaim * cmd has been completed already from timeout, just reclaim
* data ring space and free cmd * data area space and free cmd
*/ */
free_data_area(udev, cmd); free_data_area(udev, cmd);
...@@ -1128,21 +1131,10 @@ static sector_t tcmu_get_blocks(struct se_device *dev) ...@@ -1128,21 +1131,10 @@ static sector_t tcmu_get_blocks(struct se_device *dev)
dev->dev_attrib.block_size); dev->dev_attrib.block_size);
} }
static sense_reason_t
tcmu_pass_op(struct se_cmd *se_cmd)
{
int ret = tcmu_queue_cmd(se_cmd);
if (ret != 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
else
return TCM_NO_SENSE;
}
static sense_reason_t static sense_reason_t
tcmu_parse_cdb(struct se_cmd *cmd) tcmu_parse_cdb(struct se_cmd *cmd)
{ {
return passthrough_parse_cdb(cmd, tcmu_pass_op); return passthrough_parse_cdb(cmd, tcmu_queue_cmd);
} }
static const struct target_backend_ops tcmu_ops = { static const struct target_backend_ops tcmu_ops = {
......
...@@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
} }
mutex_unlock(&g_device_mutex); mutex_unlock(&g_device_mutex);
pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
return -EINVAL; return -EINVAL;
} }
...@@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op ...@@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
struct xcopy_op *xop, unsigned char *p, struct xcopy_op *xop, unsigned char *p,
unsigned short tdll) unsigned short tdll, sense_reason_t *sense_ret)
{ {
struct se_device *local_dev = se_cmd->se_dev; struct se_device *local_dev = se_cmd->se_dev;
unsigned char *desc = p; unsigned char *desc = p;
...@@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, ...@@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
unsigned short start = 0; unsigned short start = 0;
bool src = true; bool src = true;
*sense_ret = TCM_INVALID_PARAMETER_LIST;
if (offset != 0) { if (offset != 0) {
pr_err("XCOPY target descriptor list length is not" pr_err("XCOPY target descriptor list length is not"
" multiple of %d\n", XCOPY_TARGET_DESC_LEN); " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
...@@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, ...@@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true); rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
else else
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false); rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
/*
if (rc < 0) * If a matching IEEE NAA 0x83 descriptor for the requested device
* is not located on this node, return COPY_ABORTED with ASQ/ASQC
* 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
* initiator to fall back to normal copy method.
*/
if (rc < 0) {
*sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
goto out; goto out;
}
pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n", pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
xop->src_dev, &xop->src_tid_wwn[0]); xop->src_dev, &xop->src_tid_wwn[0]);
...@@ -653,6 +662,7 @@ static int target_xcopy_read_source( ...@@ -653,6 +662,7 @@ static int target_xcopy_read_source(
rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0], rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
remote_port, true); remote_port, true);
if (rc < 0) { if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0); transport_generic_free_cmd(se_cmd, 0);
return rc; return rc;
} }
...@@ -664,6 +674,7 @@ static int target_xcopy_read_source( ...@@ -664,6 +674,7 @@ static int target_xcopy_read_source(
rc = target_xcopy_issue_pt_cmd(xpt_cmd); rc = target_xcopy_issue_pt_cmd(xpt_cmd);
if (rc < 0) { if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0); transport_generic_free_cmd(se_cmd, 0);
return rc; return rc;
} }
...@@ -714,6 +725,7 @@ static int target_xcopy_write_destination( ...@@ -714,6 +725,7 @@ static int target_xcopy_write_destination(
remote_port, false); remote_port, false);
if (rc < 0) { if (rc < 0) {
struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd; struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
/* /*
* If the failure happened before the t_mem_list hand-off in * If the failure happened before the t_mem_list hand-off in
* target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
...@@ -729,6 +741,7 @@ static int target_xcopy_write_destination( ...@@ -729,6 +741,7 @@ static int target_xcopy_write_destination(
rc = target_xcopy_issue_pt_cmd(xpt_cmd); rc = target_xcopy_issue_pt_cmd(xpt_cmd);
if (rc < 0) { if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
transport_generic_free_cmd(se_cmd, 0); transport_generic_free_cmd(se_cmd, 0);
return rc; return rc;
...@@ -815,9 +828,14 @@ static void target_xcopy_do_work(struct work_struct *work) ...@@ -815,9 +828,14 @@ static void target_xcopy_do_work(struct work_struct *work)
out: out:
xcopy_pt_undepend_remotedev(xop); xcopy_pt_undepend_remotedev(xop);
kfree(xop); kfree(xop);
/*
pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n"); * Don't override an error scsi status if it has already been set
ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION; */
if (ec_cmd->scsi_status == SAM_STAT_GOOD) {
pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY"
" CHECK_CONDITION -> sending response\n", rc);
ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
}
target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION); target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION);
} }
...@@ -875,7 +893,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd) ...@@ -875,7 +893,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage, " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
tdll, sdll, inline_dl); tdll, sdll, inline_dl);
rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll); rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
if (rc <= 0) if (rc <= 0)
goto out; goto out;
......
...@@ -572,10 +572,10 @@ static void ft_send_work(struct work_struct *work) ...@@ -572,10 +572,10 @@ static void ft_send_work(struct work_struct *work)
if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
&cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
ntohl(fcp->fc_dl), task_attr, data_dir, ntohl(fcp->fc_dl), task_attr, data_dir,
TARGET_SCF_ACK_KREF)) TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID))
goto err; goto err;
pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl); pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd);
return; return;
err: err:
......
...@@ -39,6 +39,11 @@ ...@@ -39,6 +39,11 @@
#include "tcm_fc.h" #include "tcm_fc.h"
#define TFC_SESS_DBG(lport, fmt, args...) \
pr_debug("host%u: rport %6.6x: " fmt, \
(lport)->host->host_no, \
(lport)->port_id, ##args )
static void ft_sess_delete_all(struct ft_tport *); static void ft_sess_delete_all(struct ft_tport *);
/* /*
...@@ -167,24 +172,29 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) ...@@ -167,24 +172,29 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
struct ft_tport *tport; struct ft_tport *tport;
struct hlist_head *head; struct hlist_head *head;
struct ft_sess *sess; struct ft_sess *sess;
char *reason = "no session created";
rcu_read_lock(); rcu_read_lock();
tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
if (!tport) if (!tport) {
reason = "not an FCP port";
goto out; goto out;
}
head = &tport->hash[ft_sess_hash(port_id)]; head = &tport->hash[ft_sess_hash(port_id)];
hlist_for_each_entry_rcu(sess, head, hash) { hlist_for_each_entry_rcu(sess, head, hash) {
if (sess->port_id == port_id) { if (sess->port_id == port_id) {
kref_get(&sess->kref); kref_get(&sess->kref);
rcu_read_unlock(); rcu_read_unlock();
pr_debug("port_id %x found %p\n", port_id, sess); TFC_SESS_DBG(lport, "port_id %x found %p\n",
port_id, sess);
return sess; return sess;
} }
} }
out: out:
rcu_read_unlock(); rcu_read_unlock();
pr_debug("port_id %x not found\n", port_id); TFC_SESS_DBG(lport, "port_id %x not found, %s\n",
port_id, reason);
return NULL; return NULL;
} }
...@@ -195,7 +205,7 @@ static int ft_sess_alloc_cb(struct se_portal_group *se_tpg, ...@@ -195,7 +205,7 @@ static int ft_sess_alloc_cb(struct se_portal_group *se_tpg,
struct ft_tport *tport = sess->tport; struct ft_tport *tport = sess->tport;
struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)]; struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)];
pr_debug("port_id %x sess %p\n", sess->port_id, sess); TFC_SESS_DBG(tport->lport, "port_id %x sess %p\n", sess->port_id, sess);
hlist_add_head_rcu(&sess->hash, head); hlist_add_head_rcu(&sess->hash, head);
tport->sess_count++; tport->sess_count++;
...@@ -223,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, ...@@ -223,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
sess = kzalloc(sizeof(*sess), GFP_KERNEL); sess = kzalloc(sizeof(*sess), GFP_KERNEL);
if (!sess) if (!sess)
return NULL; return ERR_PTR(-ENOMEM);
kref_init(&sess->kref); /* ref for table entry */ kref_init(&sess->kref); /* ref for table entry */
sess->tport = tport; sess->tport = tport;
...@@ -234,8 +244,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, ...@@ -234,8 +244,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
TARGET_PROT_NORMAL, &initiatorname[0], TARGET_PROT_NORMAL, &initiatorname[0],
sess, ft_sess_alloc_cb); sess, ft_sess_alloc_cb);
if (IS_ERR(sess->se_sess)) { if (IS_ERR(sess->se_sess)) {
int rc = PTR_ERR(sess->se_sess);
kfree(sess); kfree(sess);
return NULL; sess = ERR_PTR(rc);
} }
return sess; return sess;
} }
...@@ -319,7 +330,7 @@ void ft_sess_close(struct se_session *se_sess) ...@@ -319,7 +330,7 @@ void ft_sess_close(struct se_session *se_sess)
mutex_unlock(&ft_lport_lock); mutex_unlock(&ft_lport_lock);
return; return;
} }
pr_debug("port_id %x\n", port_id); TFC_SESS_DBG(sess->tport->lport, "port_id %x close session\n", port_id);
ft_sess_unhash(sess); ft_sess_unhash(sess);
mutex_unlock(&ft_lport_lock); mutex_unlock(&ft_lport_lock);
ft_close_sess(sess); ft_close_sess(sess);
...@@ -379,8 +390,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, ...@@ -379,8 +390,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
if (!(fcp_parm & FCP_SPPF_INIT_FCN)) if (!(fcp_parm & FCP_SPPF_INIT_FCN))
return FC_SPP_RESP_CONF; return FC_SPP_RESP_CONF;
sess = ft_sess_create(tport, rdata->ids.port_id, rdata); sess = ft_sess_create(tport, rdata->ids.port_id, rdata);
if (!sess) if (IS_ERR(sess)) {
return FC_SPP_RESP_RES; if (PTR_ERR(sess) == -EACCES) {
spp->spp_flags &= ~FC_SPP_EST_IMG_PAIR;
return FC_SPP_RESP_CONF;
} else
return FC_SPP_RESP_RES;
}
if (!sess->params) if (!sess->params)
rdata->prli_count++; rdata->prli_count++;
sess->params = fcp_parm; sess->params = fcp_parm;
...@@ -423,8 +439,8 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, ...@@ -423,8 +439,8 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
mutex_lock(&ft_lport_lock); mutex_lock(&ft_lport_lock);
ret = ft_prli_locked(rdata, spp_len, rspp, spp); ret = ft_prli_locked(rdata, spp_len, rspp, spp);
mutex_unlock(&ft_lport_lock); mutex_unlock(&ft_lport_lock);
pr_debug("port_id %x flags %x ret %x\n", TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n",
rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret);
return ret; return ret;
} }
...@@ -477,11 +493,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) ...@@ -477,11 +493,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp)
struct ft_sess *sess; struct ft_sess *sess;
u32 sid = fc_frame_sid(fp); u32 sid = fc_frame_sid(fp);
pr_debug("sid %x\n", sid); TFC_SESS_DBG(lport, "recv sid %x\n", sid);
sess = ft_sess_get(lport, sid); sess = ft_sess_get(lport, sid);
if (!sess) { if (!sess) {
pr_debug("sid %x sess lookup failed\n", sid); TFC_SESS_DBG(lport, "sid %x sess lookup failed\n", sid);
/* TBD XXX - if FCP_CMND, send PRLO */ /* TBD XXX - if FCP_CMND, send PRLO */
fc_frame_free(fp); fc_frame_free(fp);
return; return;
......
...@@ -177,6 +177,7 @@ enum tcm_sense_reason_table { ...@@ -177,6 +177,7 @@ enum tcm_sense_reason_table {
TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15), TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED = R(0x15),
TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16), TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16),
TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17), TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17),
TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18),
#undef R #undef R
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment