Commit fcccc160 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

lib/iscsi: Factor out SCSI write payload handling into a single function



We want to move iSCSI task allocation before data buffer allocation
to use zero copy APIs in iSCSI target. As a preparation, we have to
separate PDU header and payload handling. This patch makes it a little
easier.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ib7f5ec71933fd6022fd2248aff0a0bd89b7ad830
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/470289


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent e6d090dd
Loading
Loading
Loading
Loading
+54 −35
Original line number Diff line number Diff line
@@ -3298,6 +3298,57 @@ iscsi_op_scsi_read(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task)
	return spdk_iscsi_conn_handle_queued_datain_tasks(conn);
}

static int
iscsi_op_scsi_write(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task)
{
	struct spdk_iscsi_pdu *pdu;
	struct iscsi_bhs_scsi_req *reqh;
	uint32_t transfer_len;
	uint32_t scsi_data_len;
	int rc;

	pdu = spdk_iscsi_task_get_pdu(task);
	reqh = (struct iscsi_bhs_scsi_req *)&pdu->bhs;

	transfer_len = task->scsi.transfer_len;

	if (spdk_likely(!pdu->dif_insert_or_strip)) {
		scsi_data_len = pdu->data_segment_len;
	} else {
		scsi_data_len = pdu->data_buf_len;
	}

	if (reqh->final_bit &&
	    pdu->data_segment_len < transfer_len) {
		/* needs R2T */
		rc = add_transfer_task(conn, task);
		if (rc < 0) {
			SPDK_ERRLOG("add_transfer_task() failed\n");
			spdk_iscsi_task_put(task);
			return SPDK_ISCSI_CONNECTION_FATAL;
		}

		/* Non-immediate writes */
		if (pdu->data_segment_len == 0) {
			return 0;
		} else {
			/* we are doing the first partial write task */
			task->scsi.ref++;
			spdk_scsi_task_set_data(&task->scsi, pdu->data, scsi_data_len);
			task->scsi.length = pdu->data_segment_len;
		}
	}

	if (pdu->data_segment_len == transfer_len) {
		/* we are doing small writes with no R2T */
		spdk_scsi_task_set_data(&task->scsi, pdu->data, scsi_data_len);
		task->scsi.length = transfer_len;
	}

	iscsi_queue_task(conn, task);
	return 0;
}

static int
iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
{
@@ -3307,9 +3358,8 @@ iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
	uint64_t lun;
	uint32_t task_tag;
	uint32_t transfer_len;
	uint32_t scsi_data_len;
	int F_bit, R_bit, W_bit;
	int lun_i, rc;
	int R_bit, W_bit;
	int lun_i;
	struct iscsi_bhs_scsi_req *reqh;

	if (conn->sess->session_type != SESSION_TYPE_NORMAL) {
@@ -3319,7 +3369,6 @@ iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)

	reqh = (struct iscsi_bhs_scsi_req *)&pdu->bhs;

	F_bit = reqh->final_bit;
	R_bit = reqh->read_bit;
	W_bit = reqh->write_bit;
	lun = from_be64(&reqh->lun);
@@ -3395,37 +3444,7 @@ iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
			return iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR);
		}

		if (spdk_likely(!pdu->dif_insert_or_strip)) {
			scsi_data_len = pdu->data_segment_len;
		} else {
			scsi_data_len = pdu->data_buf_len;
		}

		if (F_bit && pdu->data_segment_len < transfer_len) {
			/* needs R2T */
			rc = add_transfer_task(conn, task);
			if (rc < 0) {
				SPDK_ERRLOG("add_transfer_task() failed\n");
				spdk_iscsi_task_put(task);
				return SPDK_ISCSI_CONNECTION_FATAL;
			}

			/* Non-immediate writes */
			if (pdu->data_segment_len == 0) {
				return 0;
			} else {
				/* we are doing the first partial write task */
				task->scsi.ref++;
				spdk_scsi_task_set_data(&task->scsi, pdu->data, scsi_data_len);
				task->scsi.length = pdu->data_segment_len;
			}
		}

		if (pdu->data_segment_len == transfer_len) {
			/* we are doing small writes with no R2T */
			spdk_scsi_task_set_data(&task->scsi, pdu->data, scsi_data_len);
			task->scsi.length = transfer_len;
		}
		return iscsi_op_scsi_write(conn, task);
	} else {
		/* neither R nor W bit set */
		task->scsi.dxfer_dir = SPDK_SCSI_DIR_NONE;