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

Commit 3243f50b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target fixes from Nicholas Bellinger:
 "This contains a v4.2-rc specific RCU module unload regression bug-fix,
  a long-standing iscsi-target bug-fix for duplicate target_xfer_tags
  during NOP processing from Alexei, and two more small REPORT_LUNs
  emulation related patches to make Solaris FC host LUN scanning happy
  from Roland.

  There is also one patch not included that allows target-core to limit
  the number of fabric driver SGLs per I/O request using residuals, that
  is currently required as a work-around for FC hosts which don't honor
  EVPD block-limits settings.  At this point, it will most likely become
  for-next material"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target: Fix handling of small allocation lengths in REPORT LUNS
  target: REPORT LUNS should return LUN 0 even for dynamic ACLs
  target/iscsi: Fix double free of a TUR followed by a solicited NOPOUT
  target: Perform RCU callback barrier before backend/fabric unload
parents 3bd8f7d8 0f69a387
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -968,9 +968,9 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;

	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
	if (hdr->flags & ISCSI_FLAG_CMD_READ)
		cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
	} else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
	else
		cmd->targ_xfer_tag = 0xFFFFFFFF;
	cmd->cmd_sn		= be32_to_cpu(hdr->cmdsn);
	cmd->exp_stat_sn	= be32_to_cpu(hdr->exp_statsn);
+8 −1
Original line number Diff line number Diff line
@@ -457,8 +457,15 @@ void target_unregister_template(const struct target_core_fabric_ops *fo)
		if (!strcmp(t->tf_ops->name, fo->name)) {
			BUG_ON(atomic_read(&t->tf_access_cnt));
			list_del(&t->tf_list);
			mutex_unlock(&g_tf_lock);
			/*
			 * Wait for any outstanding fabric se_deve_entry->rcu_head
			 * callbacks to complete post kfree_rcu(), before allowing
			 * fabric driver unload of TFO->module to proceed.
			 */
			rcu_barrier();
			kfree(t);
			break;
			return;
		}
	}
	mutex_unlock(&g_tf_lock);
+9 −1
Original line number Diff line number Diff line
@@ -84,8 +84,16 @@ void target_backend_unregister(const struct target_backend_ops *ops)
	list_for_each_entry(tb, &backend_list, list) {
		if (tb->ops == ops) {
			list_del(&tb->list);
			mutex_unlock(&backend_mutex);
			/*
			 * Wait for any outstanding backend driver ->rcu_head
			 * callbacks to complete post TBO->free_device() ->
			 * call_rcu(), before allowing backend driver module
			 * unload of target_backend_ops->owner to proceed.
			 */
			rcu_barrier();
			kfree(tb);
			break;
			return;
		}
	}
	mutex_unlock(&backend_mutex);
+25 −19
Original line number Diff line number Diff line
@@ -1203,17 +1203,13 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
	struct se_dev_entry *deve;
	struct se_session *sess = cmd->se_sess;
	struct se_node_acl *nacl;
	struct scsi_lun slun;
	unsigned char *buf;
	u32 lun_count = 0, offset = 8;

	if (cmd->data_length < 16) {
		pr_warn("REPORT LUNS allocation length %u too small\n",
			cmd->data_length);
		return TCM_INVALID_CDB_FIELD;
	}
	__be32 len;

	buf = transport_kmap_data_sg(cmd);
	if (!buf)
	if (cmd->data_length && !buf)
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;

	/*
@@ -1221,11 +1217,9 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
	 * coming via a target_core_mod PASSTHROUGH op, and not through
	 * a $FABRIC_MOD.  In that case, report LUN=0 only.
	 */
	if (!sess) {
		int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
		lun_count = 1;
	if (!sess)
		goto done;
	}

	nacl = sess->se_node_acl;

	rcu_read_lock();
@@ -1236,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
		 * See SPC2-R20 7.19.
		 */
		lun_count++;
		if ((offset + 8) > cmd->data_length)
		if (offset >= cmd->data_length)
			continue;

		int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
		int_to_scsilun(deve->mapped_lun, &slun);
		memcpy(buf + offset, &slun,
		       min(8u, cmd->data_length - offset));
		offset += 8;
	}
	rcu_read_unlock();
@@ -1248,12 +1244,22 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
	 * See SPC3 r07, page 159.
	 */
done:
	lun_count *= 8;
	buf[0] = ((lun_count >> 24) & 0xff);
	buf[1] = ((lun_count >> 16) & 0xff);
	buf[2] = ((lun_count >> 8) & 0xff);
	buf[3] = (lun_count & 0xff);
	/*
	 * If no LUNs are accessible, report virtual LUN 0.
	 */
	if (lun_count == 0) {
		int_to_scsilun(0, &slun);
		if (cmd->data_length > 8)
			memcpy(buf + offset, &slun,
			       min(8u, cmd->data_length - offset));
		lun_count = 1;
	}

	if (buf) {
		len = cpu_to_be32(lun_count * 8);
		memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length));
		transport_kunmap_data_sg(cmd);
	}

	target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
	return 0;