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: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ib7f5ec71933fd6022fd2248aff0a0bd89b7ad830
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/470289
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-10-03 14:47:02 +09:00 committed by Tomasz Zawadzki
parent e6d090dddf
commit fcccc16095

View File

@ -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;