iscsi: Add an API to return DIF context of SCSI command

Ths patch adds an API spdk_iscsi_get_dif_ctx().

When opcode of BHS is SCSI command, spdk_iscsi_get_dif_ctx() extracts
CDB and LUN ID from BHS. When opcode of BHS is Data Out or Data In,
spdk_iscsi_get_dif_ctx() extracts TTT and get R2T task corresponding
to TTT, and gets CDB and LUN ID from the task.

Then spdk_iscsi_get_dif_ctx() gets LUN by using LUN ID and calls
spdk_scsi_lun_get_dif_ctx().

Additionally spdk_iscsi_get_dif_ctx() checks the state of the connection
and the type of the session is valid before starting decode operation
because contents of PDU is not reliable when the state of the connection
is invalid. The necessity of the check was found by the Calsoft test tool.
Checks and test cases are not matched yet but copying existing checks
from spdk_iscsi_conn_execute, spdk_iscsi_op_scsi, and spdk_iscsi_op_data
will be enough. The check added for Data Out is not necessary for Data In
but it will not be harmful for Data In.

Change-Id: Iba09e0ac3e760aa1c5b582a120596c49b9e9d51e
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446231
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-02-26 17:37:05 +09:00 committed by Changpeng Liu
parent 8697bce7af
commit b8a51ff5b8
2 changed files with 72 additions and 0 deletions

View File

@ -4559,6 +4559,76 @@ spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
return 0;
}
bool
spdk_iscsi_get_dif_ctx(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
struct spdk_dif_ctx *dif_ctx)
{
struct iscsi_bhs *bhs;
uint32_t offset = 0;
uint8_t *cdb = NULL;
uint64_t lun;
int lun_id = 0;
struct spdk_scsi_lun *lun_dev;
/* connection is not in full feature phase but non-login opcode
* was received.
*/
if ((!conn->full_feature && conn->state == ISCSI_CONN_STATE_RUNNING) ||
conn->state == ISCSI_CONN_STATE_INVALID) {
return false;
}
/* SCSI Command is allowed only in normal session */
if (conn->sess == NULL ||
conn->sess->session_type != SESSION_TYPE_NORMAL) {
return false;
}
bhs = &pdu->bhs;
switch (bhs->opcode) {
case ISCSI_OP_SCSI: {
struct iscsi_bhs_scsi_req *sbhs;
sbhs = (struct iscsi_bhs_scsi_req *)bhs;
offset = 0;
cdb = sbhs->cdb;
lun = from_be64(&sbhs->lun);
lun_id = spdk_islun2lun(lun);
break;
}
case ISCSI_OP_SCSI_DATAIN:
case ISCSI_OP_SCSI_DATAOUT: {
/* Location of Buffer Offset and TTT in PDU are same
* for Data In and Out, so unify them.
*/
struct iscsi_bhs_data_in *dbhs;
struct spdk_iscsi_task *task;
int transfer_tag;
dbhs = (struct iscsi_bhs_data_in *)bhs;
offset = from_be32(&dbhs->buffer_offset);
transfer_tag = from_be32(&dbhs->ttt);
task = spdk_get_transfer_task(conn, transfer_tag);
if (task == NULL) {
return false;
}
cdb = task->scsi.cdb;
lun_id = task->lun_id;
break;
}
default:
return false;
}
lun_dev = spdk_scsi_dev_get_lun(conn->dev, lun_id);
if (lun_dev == NULL) {
return false;
}
return spdk_scsi_lun_get_dif_ctx(lun_dev, cdb, offset, dif_ctx);
}
void spdk_free_sess(struct spdk_iscsi_sess *sess)
{
if (sess == NULL) {

View File

@ -408,6 +408,8 @@ int spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
int spdk_iscsi_build_iovs(struct spdk_iscsi_conn *conn, struct iovec *iovs, int num_iovs,
struct spdk_iscsi_pdu *pdu, uint32_t *mapped_length);
int spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu);
bool spdk_iscsi_get_dif_ctx(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
struct spdk_dif_ctx *dif_ctx);
void spdk_iscsi_task_mgmt_response(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_task *task);