Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13caa8ed authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target fixes from Nicholas Bellinger:
 "Here are the outstanding target fixes queued up for v3.12-rc4 code.

  The highlights include:

   - Make vhost/scsi tag percpu_ida_alloc() use GFP_ATOMIC
   - Allow sess_cmd_map allocation failure fallback to use vzalloc
   - Fix COMPARE_AND_WRITE se_cmd->data_length bug with FILEIO backends
   - Fixes for COMPARE_AND_WRITE callback recursive failure OOPs + non
     zero scsi_status bug
   - Make iscsi-target do acknowledgement tag release from RX context
   - Setup iscsi-target with extra (cmdsn_depth / 2) percpu_ida tags

  Also included is a iscsi-target patch CC'ed for v3.10+ that avoids
  legacy wait_for_task=true release during fast-past StatSN
  acknowledgement, and two other SRP target related patches that address
  long-standing issues that are CC'ed for v3.3+.

  Extra thanks to Thomas Glanzmann for his testing feedback with
  COMPARE_AND_WRITE + EXTENDED_COPY VAAI logic"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  iscsi-target; Allow an extra tag_num / 2 number of percpu_ida tags
  iscsi-target: Perform release of acknowledged tags from RX context
  iscsi-target: Only perform wait_for_tasks when performing shutdown
  target: Fail on non zero scsi_status in compare_and_write_callback
  target: Fix recursive COMPARE_AND_WRITE callback failure
  target: Reset data_length for COMPARE_AND_WRITE to NoLB * block_size
  ib_srpt: always set response for task management
  target: Fall back to vzalloc upon ->sess_cmd_map kzalloc failure
  vhost/scsi: Use GFP_ATOMIC with percpu_ida_alloc for obtaining tag
  ib_srpt: Destroy cm_id before destroying QP.
  target: Fix xop->dbl assignment in target_xcopy_parse_segdesc_02
parents 831ae3c1 9e20ae33
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -1588,7 +1588,7 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
	int resp_data_len;
	int resp_len;

	resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
	resp_data_len = 4;
	resp_len = sizeof(*srp_rsp) + resp_data_len;

	srp_rsp = ioctx->ioctx.buf;
@@ -1600,11 +1600,9 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
				    + atomic_xchg(&ch->req_lim_delta, 0));
	srp_rsp->tag = tag;

	if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
	srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
	srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
	srp_rsp->data[3] = rsp_code;
	}

	return resp_len;
}
@@ -2358,6 +2356,8 @@ static void srpt_release_channel_work(struct work_struct *w)
	transport_deregister_session(se_sess);
	ch->sess = NULL;

	ib_destroy_cm_id(ch->cm_id);

	srpt_destroy_ch_ib(ch);

	srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
@@ -2368,8 +2368,6 @@ static void srpt_release_channel_work(struct work_struct *w)
	list_del(&ch->list);
	spin_unlock_irq(&sdev->spinlock);

	ib_destroy_cm_id(ch->cm_id);

	if (ch->release_done)
		complete(ch->release_done);

+9 −4
Original line number Diff line number Diff line
@@ -753,7 +753,8 @@ static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)

static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
{
	struct iscsi_cmd *cmd;
	LIST_HEAD(ack_list);
	struct iscsi_cmd *cmd, *cmd_p;

	conn->exp_statsn = exp_statsn;

@@ -761,19 +762,23 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
		return;

	spin_lock_bh(&conn->cmd_lock);
	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
	list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
		spin_lock(&cmd->istate_lock);
		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
			cmd->i_state = ISTATE_REMOVE;
			spin_unlock(&cmd->istate_lock);
			iscsit_add_cmd_to_immediate_queue(cmd, conn,
						cmd->i_state);
			list_move_tail(&cmd->i_conn_node, &ack_list);
			continue;
		}
		spin_unlock(&cmd->istate_lock);
	}
	spin_unlock_bh(&conn->cmd_lock);

	list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
		list_del(&cmd->i_conn_node);
		iscsit_free_cmd(cmd, false);
	}
}

static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
+1 −1
Original line number Diff line number Diff line
@@ -1192,7 +1192,7 @@ int iscsi_target_locate_portal(
	 */
alloc_tags:
	tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
	tag_num += ISCSIT_EXTRA_TAGS;
	tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS;
	tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;

	ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);
+2 −2
Original line number Diff line number Diff line
@@ -736,7 +736,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
		 * Fallthrough
		 */
	case ISCSI_OP_SCSI_TMFUNC:
		rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
		rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
		if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
			__iscsit_free_cmd(cmd, true, shutdown);
			target_put_sess_cmd(se_cmd->se_sess, se_cmd);
@@ -752,7 +752,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
			se_cmd = &cmd->se_cmd;
			__iscsit_free_cmd(cmd, true, shutdown);

			rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
			rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
			if (!rc && shutdown && se_cmd->se_sess) {
				__iscsit_free_cmd(cmd, true, shutdown);
				target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+26 −2
Original line number Diff line number Diff line
@@ -349,7 +349,16 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
{
	struct se_device *dev = cmd->se_dev;

	/*
	 * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
	 * within target_complete_ok_work() if the command was successfully
	 * sent to the backend driver.
	 */
	spin_lock_irq(&cmd->t_state_lock);
	if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
		cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
	spin_unlock_irq(&cmd->t_state_lock);

	/*
	 * Unlock ->caw_sem originally obtained during sbc_compare_and_write()
	 * before the original READ I/O submission.
@@ -363,7 +372,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
{
	struct se_device *dev = cmd->se_dev;
	struct scatterlist *write_sg = NULL, *sg;
	unsigned char *buf, *addr;
	unsigned char *buf = NULL, *addr;
	struct sg_mapping_iter m;
	unsigned int offset = 0, len;
	unsigned int nlbas = cmd->t_task_nolb;
@@ -378,6 +387,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
	 */
	if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
		return TCM_NO_SENSE;
	/*
	 * Immediately exit + release dev->caw_sem if command has already
	 * been failed with a non-zero SCSI status.
	 */
	if (cmd->scsi_status) {
		pr_err("compare_and_write_callback: non zero scsi_status:"
			" 0x%02x\n", cmd->scsi_status);
		goto out;
	}

	buf = kzalloc(cmd->data_length, GFP_KERNEL);
	if (!buf) {
@@ -508,6 +526,12 @@ sbc_compare_and_write(struct se_cmd *cmd)
		cmd->transport_complete_callback = NULL;
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
	}
	/*
	 * Reset cmd->data_length to individual block_size in order to not
	 * confuse backend drivers that depend on this value matching the
	 * size of the I/O being submitted.
	 */
	cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;

	ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
			      DMA_FROM_DEVICE);
Loading