mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 11:41:26 +00:00
Behavior changes:
- Fixed: the SCSOLNT and UCSOLNT bits were ignored in received SRP requests, and the SOLNT bit was not set in responses when required. This is required by the SRP protocol specification. - Fixed: SRP_RSP messages must be limited to the MAXIMUM TARGET TO INITIATOR IU LENGTH field indicated in the SRP_LOGIN_RSP response instead of the maximum message size supported by SRPT. This is also required by the SRP protocol specification. - Fixed: the STATUS field of response messages with status GOOD and that contain sense data is no longer modified into CHECK CONDITION. Internal changes (refactoring): - Replaced the SCSI sense data handling data structures and code in SRPT by those of the SCST core. - Moved the code for building an error response from srpt_handle_cmd() and srpt_handle_tsk_mgmt() to srpt_handle_new_iu(). - Removed the ioctx::data_len member. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1416 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -806,7 +806,22 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
|
||||
/**
|
||||
* srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
|
||||
* @ioctx: Pointer to the I/O context associated with the request.
|
||||
* @srp_cmd: Pointer to the SRP_CMD request data.
|
||||
* @dir: Pointer to the variable to which the transfer direction will be
|
||||
* written.
|
||||
* @data_len: Pointer to the variable to which the total data length of all
|
||||
* descriptors in the SRP_CMD request will be written.
|
||||
*
|
||||
* This function initializes ioctx->nrbuf and ioctx->r_bufs.
|
||||
*
|
||||
* Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
|
||||
* -ENOMEM when memory allocation fails and zero upon success.
|
||||
*/
|
||||
static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd,
|
||||
scst_data_direction *dir, u64 *data_len)
|
||||
{
|
||||
struct srp_indirect_buf *idb;
|
||||
struct srp_direct_buf *db;
|
||||
@@ -815,7 +830,8 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
|
||||
|
||||
/*
|
||||
* The pointer computations below will only be compiled correctly
|
||||
* if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[].
|
||||
* if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
|
||||
* whether srp_cmd::add_data has been declared as a byte pointer.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
|
||||
BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
|
||||
@@ -824,7 +840,25 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
|
||||
/* Note: the __same_type() macro has been introduced in kernel 2.6.31.*/
|
||||
#endif
|
||||
|
||||
BUG_ON(!dir);
|
||||
BUG_ON(!data_len);
|
||||
|
||||
ret = 0;
|
||||
*data_len = 0;
|
||||
|
||||
/*
|
||||
* The lower four bits of the buffer format field contain the DATA-IN
|
||||
* buffer descriptor format, and the highest four bits contain the
|
||||
* DATA-OUT buffer descriptor format.
|
||||
*/
|
||||
*dir = SCST_DATA_NONE;
|
||||
if (srp_cmd->buf_fmt & 0xf)
|
||||
/* DATA-IN: transfer data from target to initiator. */
|
||||
*dir = SCST_DATA_READ;
|
||||
else if (srp_cmd->buf_fmt >> 4)
|
||||
/* DATA-OUT: transfer data from initiator to target. */
|
||||
*dir = SCST_DATA_WRITE;
|
||||
|
||||
/*
|
||||
* According to the SRP spec, the lower two bits of the 'ADDITIONAL
|
||||
* CDB LENGTH' field are reserved and the size in bytes of this field
|
||||
@@ -839,8 +873,9 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
|
||||
db = (struct srp_direct_buf *)(srp_cmd->add_data
|
||||
+ add_cdb_offset);
|
||||
memcpy(ioctx->rbufs, db, sizeof *db);
|
||||
ioctx->data_len = be32_to_cpu(db->len);
|
||||
} else {
|
||||
*data_len = be32_to_cpu(db->len);
|
||||
} else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
|
||||
((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
|
||||
idb = (struct srp_indirect_buf *)(srp_cmd->add_data
|
||||
+ add_cdb_offset);
|
||||
|
||||
@@ -873,7 +908,7 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
|
||||
|
||||
db = idb->desc_list;
|
||||
memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
|
||||
ioctx->data_len = be32_to_cpu(idb->len);
|
||||
*data_len = be32_to_cpu(idb->len);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
@@ -1106,12 +1141,15 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SRP_RSP response.
|
||||
* srpt_build_cmd_rsp() - Build an SRP_RSP response.
|
||||
* @ch: RDMA channel through which the request has been received.
|
||||
* @ioctx: I/O context in which the SRP_RSP response will be built.
|
||||
* @s_key: sense key that will be stored in the response.
|
||||
* @s_code: value that will be stored in the asc_ascq field of the sense data.
|
||||
* @ioctx: I/O context associated with the SRP_CMD request. The response will
|
||||
* be built in the buffer ioctx->buf points at and hence this function will
|
||||
* overwrite the request data.
|
||||
* @tag: tag of the request for which this response is being generated.
|
||||
* @status: value for the STATUS field of the SRP_RSP information unit.
|
||||
* @sense_data: pointer to sense data to be included in the response.
|
||||
* @sense_data_len: length in bytes of the sense data.
|
||||
*
|
||||
* Returns the size in bytes of the SRP_RSP response.
|
||||
*
|
||||
@@ -1120,40 +1158,56 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
|
||||
* response. See also SPC-2 for more information about sense data.
|
||||
*/
|
||||
static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
|
||||
struct srpt_ioctx *ioctx, u8 s_key, u8 s_code,
|
||||
u64 tag)
|
||||
struct srpt_ioctx *ioctx, u64 tag, int status,
|
||||
const u8 *sense_data, int sense_data_len)
|
||||
{
|
||||
struct srp_rsp *srp_rsp;
|
||||
struct sense_data *sense;
|
||||
int limit_delta;
|
||||
int sense_data_len;
|
||||
int resp_len;
|
||||
int max_sense_len;
|
||||
|
||||
sense_data_len = (s_key == NO_SENSE) ? 0 : sizeof(*sense);
|
||||
resp_len = sizeof(*srp_rsp) + sense_data_len;
|
||||
/*
|
||||
* The lowest bit of all SAM-3 status codes is zero (see also
|
||||
* paragraph 5.3 in SAM-3).
|
||||
*/
|
||||
WARN_ON(status & 1);
|
||||
|
||||
srp_rsp = ioctx->buf;
|
||||
BUG_ON(!srp_rsp);
|
||||
memset(srp_rsp, 0, sizeof *srp_rsp);
|
||||
|
||||
limit_delta = atomic_read(&ch->req_lim_delta);
|
||||
atomic_sub(limit_delta, &ch->req_lim_delta);
|
||||
|
||||
srp_rsp->opcode = SRP_RSP;
|
||||
/*
|
||||
* Copy the SCSOLNT or UCSOLNT bit from the request to the SOLNT bit
|
||||
* of the response.
|
||||
*/
|
||||
srp_rsp->sol_not
|
||||
= (ioctx->sol_not
|
||||
& (status == SAM_STAT_GOOD ? SRP_SCSOLNT : SRP_UCSOLNT))
|
||||
? SRP_SOLNT : 0;
|
||||
srp_rsp->req_lim_delta = cpu_to_be32(limit_delta);
|
||||
srp_rsp->tag = tag;
|
||||
|
||||
if (s_key != NO_SENSE) {
|
||||
if (SCST_SENSE_VALID(sense_data)) {
|
||||
BUILD_BUG_ON(MIN_MAX_MESSAGE_SIZE <= sizeof(*srp_rsp));
|
||||
max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
|
||||
if (sense_data_len > max_sense_len) {
|
||||
PRINT_WARNING("truncated sense data from %d to %d"
|
||||
" bytes", sense_data_len,
|
||||
max_sense_len);
|
||||
sense_data_len = max_sense_len;
|
||||
}
|
||||
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
|
||||
srp_rsp->status = SAM_STAT_CHECK_CONDITION;
|
||||
srp_rsp->status = status;
|
||||
srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
|
||||
memcpy(srp_rsp + 1, sense_data, sense_data_len);
|
||||
} else
|
||||
sense_data_len = 0;
|
||||
|
||||
sense = (struct sense_data *)(srp_rsp + 1);
|
||||
sense->err_code = 0x70;
|
||||
sense->key = s_key;
|
||||
sense->asc_ascq = s_code;
|
||||
}
|
||||
|
||||
return resp_len;
|
||||
return sizeof(*srp_rsp) + sense_data_len;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1188,6 +1242,15 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
|
||||
atomic_sub(limit_delta, &ch->req_lim_delta);
|
||||
|
||||
srp_rsp->opcode = SRP_RSP;
|
||||
/*
|
||||
* Copy the SCSOLNT or UCSOLNT bit from the request to the SOLNT bit
|
||||
* of the response.
|
||||
*/
|
||||
srp_rsp->sol_not
|
||||
= (ioctx->sol_not
|
||||
& (rsp_code == SRP_TSK_MGMT_SUCCESS
|
||||
? SRP_SCSOLNT : SRP_UCSOLNT))
|
||||
? SRP_SOLNT : 0;
|
||||
srp_rsp->req_lim_delta = cpu_to_be32(limit_delta);
|
||||
srp_rsp->tag = tag;
|
||||
|
||||
@@ -1207,48 +1270,27 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
|
||||
{
|
||||
struct scst_cmd *scmnd;
|
||||
struct srp_cmd *srp_cmd;
|
||||
struct srp_rsp *srp_rsp;
|
||||
scst_data_direction dir;
|
||||
u64 data_len;
|
||||
int ret;
|
||||
|
||||
srp_cmd = ioctx->buf;
|
||||
srp_rsp = ioctx->buf;
|
||||
|
||||
dir = SCST_DATA_NONE;
|
||||
if (srp_cmd->buf_fmt) {
|
||||
ret = srpt_get_desc_tbl(ioctx, srp_cmd);
|
||||
if (ret) {
|
||||
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
|
||||
NO_ADD_SENSE, srp_cmd->tag);
|
||||
srp_rsp->status = SAM_STAT_TASK_SET_FULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lower four bits of the buffer format field contain the
|
||||
* DATA-IN buffer descriptor format, and the highest four bits
|
||||
* contain the DATA-OUT buffer descriptor format.
|
||||
*/
|
||||
if (srp_cmd->buf_fmt & 0xf)
|
||||
/* DATA-IN: transfer data from target to initiator. */
|
||||
dir = SCST_DATA_READ;
|
||||
else if (srp_cmd->buf_fmt >> 4)
|
||||
/* DATA-OUT: transfer data from initiator to target. */
|
||||
dir = SCST_DATA_WRITE;
|
||||
}
|
||||
|
||||
scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) &srp_cmd->lun,
|
||||
sizeof srp_cmd->lun, srp_cmd->cdb, 16,
|
||||
thread ? SCST_NON_ATOMIC : SCST_ATOMIC);
|
||||
if (!scmnd) {
|
||||
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
|
||||
NO_ADD_SENSE, srp_cmd->tag);
|
||||
srp_rsp->status = SAM_STAT_TASK_SET_FULL;
|
||||
if (!scmnd)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ioctx->scmnd = scmnd;
|
||||
|
||||
ret = srpt_get_desc_tbl(ioctx, srp_cmd, &dir, &data_len);
|
||||
if (ret) {
|
||||
scst_set_cmd_error(scmnd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (srp_cmd->task_attr) {
|
||||
case SRP_CMD_HEAD_OF_Q:
|
||||
scmnd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
|
||||
@@ -1269,21 +1311,19 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
|
||||
|
||||
scst_cmd_set_tag(scmnd, srp_cmd->tag);
|
||||
scst_cmd_set_tgt_priv(scmnd, ioctx);
|
||||
scst_cmd_set_expected(scmnd, dir, ioctx->data_len);
|
||||
scst_cmd_set_expected(scmnd, dir, data_len);
|
||||
scst_cmd_init_done(scmnd, scst_estimate_context());
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
WARN_ON(srp_rsp->opcode != SRP_RSP);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an SRP_TSK_MGMT request.
|
||||
* srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
|
||||
*
|
||||
* Returns 0 upon success and -1 upon failure.
|
||||
* Returns SRP_TSK_MGMT_SUCCESS upon success.
|
||||
*
|
||||
* Each task management function is performed by calling one of the
|
||||
* scst_rx_mgmt_fn*() functions. These functions will either report failure
|
||||
@@ -1296,12 +1336,13 @@ err:
|
||||
* For more information about SRP_TSK_MGMT information units, see also section
|
||||
* 6.7 in the T10 SRP r16a document.
|
||||
*/
|
||||
static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
||||
struct srpt_ioctx *ioctx)
|
||||
static u8 srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
||||
struct srpt_ioctx *ioctx)
|
||||
{
|
||||
struct srp_tsk_mgmt *srp_tsk;
|
||||
struct srpt_mgmt_ioctx *mgmt_ioctx;
|
||||
int ret;
|
||||
u8 srp_tsk_mgmt_status;
|
||||
|
||||
srp_tsk = ioctx->buf;
|
||||
|
||||
@@ -1312,12 +1353,10 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
||||
(unsigned long long) srp_tsk->tag,
|
||||
ch->cm_id, ch->scst_sess);
|
||||
|
||||
srp_tsk_mgmt_status = SRP_TSK_MGMT_FAILED;
|
||||
mgmt_ioctx = kmalloc(sizeof *mgmt_ioctx, GFP_ATOMIC);
|
||||
if (!mgmt_ioctx) {
|
||||
srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED,
|
||||
srp_tsk->tag);
|
||||
if (!mgmt_ioctx)
|
||||
goto err;
|
||||
}
|
||||
|
||||
mgmt_ioctx->ioctx = ioctx;
|
||||
mgmt_ioctx->ch = ch;
|
||||
@@ -1375,28 +1414,42 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
||||
break;
|
||||
default:
|
||||
TRACE_DBG("%s", "Unsupported task management function.");
|
||||
srpt_build_tskmgmt_rsp(ch, ioctx,
|
||||
SRP_TSK_MGMT_FUNC_NOT_SUPP,
|
||||
srp_tsk->tag);
|
||||
srp_tsk_mgmt_status = SRP_TSK_MGMT_FUNC_NOT_SUPP;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
TRACE_DBG("%s", "Processing task management function failed.");
|
||||
srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED,
|
||||
srp_tsk->tag);
|
||||
TRACE_DBG("Processing task management function failed"
|
||||
" (ret = %d).", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
WARN_ON(srp_tsk->opcode == SRP_RSP);
|
||||
|
||||
return 0;
|
||||
return SRP_TSK_MGMT_SUCCESS;
|
||||
|
||||
err:
|
||||
WARN_ON(srp_tsk->opcode != SRP_RSP);
|
||||
|
||||
kfree(mgmt_ioctx);
|
||||
return -1;
|
||||
return srp_tsk_mgmt_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_sense() - A copy of the function with the same name in
|
||||
* scst/src/common.c.
|
||||
*/
|
||||
static int set_sense(uint8_t *buffer, int len, int key, int asc, int ascq)
|
||||
{
|
||||
int res = 18;
|
||||
|
||||
EXTRACHECKS_BUG_ON(len < res);
|
||||
|
||||
memset(buffer, 0, res);
|
||||
|
||||
buffer[0] = 0x70; /* Error Code */
|
||||
buffer[2] = key; /* Sense Key */
|
||||
buffer[7] = 0x0a; /* Additional Sense Length */
|
||||
buffer[12] = asc; /* ASC */
|
||||
buffer[13] = ascq; /* ASCQ */
|
||||
|
||||
TRACE_BUFFER("Sense set", buffer, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1408,10 +1461,25 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
|
||||
struct srpt_ioctx *ioctx)
|
||||
{
|
||||
struct srp_cmd *srp_cmd;
|
||||
struct srp_rsp *srp_rsp;
|
||||
enum rdma_ch_state ch_state;
|
||||
u8 srp_response_status;
|
||||
u8 srp_tsk_mgmt_status;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* A quote from SAM-3, paragraph 4.9.6: "Any command that is not
|
||||
* relayed to a dependent logical unit shall be terminated with a
|
||||
* CHECK CONDITION status. The sense key shall be set to ILLEGAL
|
||||
* REQUEST and the additional sense code shall be set to INVALID
|
||||
* COMMAND OPERATION CODE. If a task management function cannot be
|
||||
* relayed to a dependent logical unit, a service response of SERVICE
|
||||
* DELIVERY OR TARGET FAILURE shall be returned."
|
||||
*/
|
||||
|
||||
srp_response_status = SAM_STAT_CHECK_CONDITION;
|
||||
/* To keep the compiler happy. */
|
||||
srp_tsk_mgmt_status = -1;
|
||||
|
||||
ch_state = atomic_read(&ch->state);
|
||||
if (ch_state == RDMA_CHANNEL_CONNECTING) {
|
||||
list_add_tail(&ioctx->wait_list, &ch->cmd_wait_list);
|
||||
@@ -1427,7 +1495,8 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
|
||||
ioctx->dma, srp_max_message_size,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
ioctx->data_len = 0;
|
||||
srp_cmd = ioctx->buf;
|
||||
|
||||
ioctx->n_rbuf = 0;
|
||||
ioctx->rbufs = NULL;
|
||||
ioctx->n_rdma = 0;
|
||||
@@ -1435,44 +1504,65 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
|
||||
ioctx->rdma_ius = NULL;
|
||||
ioctx->scmnd = NULL;
|
||||
ioctx->ch = ch;
|
||||
ioctx->sol_not = srp_cmd->sol_not;
|
||||
atomic_set(&ioctx->state, SRPT_STATE_NEW);
|
||||
|
||||
srp_cmd = ioctx->buf;
|
||||
srp_rsp = ioctx->buf;
|
||||
|
||||
switch (srp_cmd->opcode) {
|
||||
case SRP_CMD:
|
||||
if (srpt_handle_cmd(ch, ioctx) < 0)
|
||||
if (srpt_handle_cmd(ch, ioctx) < 0) {
|
||||
if (ioctx->scmnd)
|
||||
srp_response_status =
|
||||
scst_cmd_get_status(ioctx->scmnd);
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
|
||||
case SRP_TSK_MGMT:
|
||||
if (srpt_handle_tsk_mgmt(ch, ioctx) < 0)
|
||||
srp_tsk_mgmt_status = srpt_handle_tsk_mgmt(ch, ioctx);
|
||||
if (srp_tsk_mgmt_status != SRP_TSK_MGMT_SUCCESS)
|
||||
goto err;
|
||||
break;
|
||||
|
||||
case SRP_I_LOGOUT:
|
||||
case SRP_AER_REQ:
|
||||
default:
|
||||
srpt_build_cmd_rsp(ch, ioctx, ILLEGAL_REQUEST, INVALID_CDB,
|
||||
srp_cmd->tag);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
WARN_ON(srp_rsp->opcode != SRP_RSP);
|
||||
len = (sizeof *srp_rsp) + be32_to_cpu(srp_rsp->sense_data_len);
|
||||
|
||||
ch_state = atomic_read(&ch->state);
|
||||
if (ch_state != RDMA_CHANNEL_LIVE) {
|
||||
/* Give up if another thread modified the channel state. */
|
||||
PRINT_ERROR("%s: channel is in state %d", __func__, ch_state);
|
||||
srpt_reset_ioctx(ch, ioctx);
|
||||
} else if (srpt_post_send(ch, ioctx, len)) {
|
||||
PRINT_ERROR("%s: sending SRP_RSP response failed", __func__);
|
||||
srpt_reset_ioctx(ch, ioctx);
|
||||
} else {
|
||||
if (srp_cmd->opcode == SRP_TSK_MGMT) {
|
||||
len = srpt_build_tskmgmt_rsp(ch, ioctx,
|
||||
srp_tsk_mgmt_status,
|
||||
((struct srp_tsk_mgmt *)srp_cmd)->tag);
|
||||
} else if (ioctx->scmnd)
|
||||
len = srpt_build_cmd_rsp(ch, ioctx, srp_cmd->tag,
|
||||
srp_response_status,
|
||||
scst_cmd_get_sense_buffer(ioctx->scmnd),
|
||||
scst_cmd_get_sense_buffer_len(ioctx->scmnd));
|
||||
else {
|
||||
u8 sense_buf[18];
|
||||
int sense_len;
|
||||
|
||||
sense_len = set_sense(sense_buf,
|
||||
ARRAY_SIZE(sense_buf),
|
||||
scst_sense_invalid_field_in_cdb);
|
||||
len = srpt_build_cmd_rsp(ch, ioctx, srp_cmd->tag,
|
||||
srp_response_status,
|
||||
sense_buf, sense_len);
|
||||
}
|
||||
if (srpt_post_send(ch, ioctx, len)) {
|
||||
PRINT_ERROR("%s: sending SRP_RSP response failed",
|
||||
__func__);
|
||||
srpt_reset_ioctx(ch, ioctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,7 +1855,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
it_iu_len = be32_to_cpu(req->req_it_iu_len);
|
||||
|
||||
PRINT_INFO("Received SRP_LOGIN_REQ with"
|
||||
" i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and length %d"
|
||||
" i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and it_iu_len %d"
|
||||
" on port %d (guid=0x%llx:0x%llx)",
|
||||
(unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[0]),
|
||||
(unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[8]),
|
||||
@@ -1945,6 +2035,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
rsp->tag = req->tag;
|
||||
rsp->max_it_iu_len = req->req_it_iu_len;
|
||||
rsp->max_ti_iu_len = req->req_it_iu_len;
|
||||
ch->max_ti_iu_len = req->req_it_iu_len;
|
||||
rsp->buf_fmt =
|
||||
cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT);
|
||||
rsp->req_lim_delta = cpu_to_be32(SRPT_RQ_SIZE);
|
||||
@@ -2463,19 +2554,19 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the SCST core. Transmits the response buffer and status held in
|
||||
* 'scmnd'. Must not block.
|
||||
/**
|
||||
* srpt_xmit_response() - SCST callback function that transmits the response
|
||||
* to a SCSI command.
|
||||
*
|
||||
* Must not block.
|
||||
*/
|
||||
static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
{
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct srpt_ioctx *ioctx;
|
||||
struct srp_rsp *srp_rsp;
|
||||
u64 tag;
|
||||
int ret = SCST_TGT_RES_SUCCESS;
|
||||
int dir;
|
||||
int status;
|
||||
int resp_len;
|
||||
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
@@ -2497,56 +2588,30 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
tag = scst_cmd_get_tag(scmnd);
|
||||
dir = scst_cmd_get_data_direction(scmnd);
|
||||
status = scst_cmd_get_status(scmnd) & 0xff;
|
||||
|
||||
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE, NO_ADD_SENSE, tag);
|
||||
|
||||
srp_rsp = ioctx->buf;
|
||||
|
||||
if (SCST_SENSE_VALID(scst_cmd_get_sense_buffer(scmnd))) {
|
||||
unsigned int max_sense_len;
|
||||
|
||||
srp_rsp->sense_data_len = scst_cmd_get_sense_buffer_len(scmnd);
|
||||
BUILD_BUG_ON(MIN_MAX_MESSAGE_SIZE <= sizeof(*srp_rsp));
|
||||
WARN_ON(srp_max_message_size <= sizeof(*srp_rsp));
|
||||
max_sense_len = srp_max_message_size - sizeof(*srp_rsp);
|
||||
if (srp_rsp->sense_data_len > max_sense_len) {
|
||||
PRINT_WARNING("truncated sense data from %d to %d"
|
||||
" bytes", srp_rsp->sense_data_len,
|
||||
max_sense_len);
|
||||
srp_rsp->sense_data_len = max_sense_len;
|
||||
}
|
||||
|
||||
memcpy((u8 *) (srp_rsp + 1), scst_cmd_get_sense_buffer(scmnd),
|
||||
srp_rsp->sense_data_len);
|
||||
|
||||
srp_rsp->sense_data_len = cpu_to_be32(srp_rsp->sense_data_len);
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
|
||||
|
||||
if (!status)
|
||||
status = SAM_STAT_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
srp_rsp->status = status;
|
||||
|
||||
/* For read commands, transfer the data to the initiator. */
|
||||
if (dir == SCST_DATA_READ && scst_cmd_get_resp_data_len(scmnd)) {
|
||||
ret = srpt_xfer_data(ch, ioctx, scmnd);
|
||||
if (ret != SCST_TGT_RES_SUCCESS) {
|
||||
PRINT_ERROR("%s: tag= %lld xfer_data failed",
|
||||
__func__, (unsigned long long)tag);
|
||||
__func__,
|
||||
(unsigned long long)
|
||||
scst_cmd_get_tag(scmnd));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (srpt_post_send(ch, ioctx,
|
||||
sizeof *srp_rsp +
|
||||
be32_to_cpu(srp_rsp->sense_data_len))) {
|
||||
resp_len = srpt_build_cmd_rsp(ch, ioctx,
|
||||
scst_cmd_get_tag(scmnd),
|
||||
scst_cmd_get_status(scmnd),
|
||||
scst_cmd_get_sense_buffer(scmnd),
|
||||
scst_cmd_get_sense_buffer_len(scmnd));
|
||||
|
||||
if (srpt_post_send(ch, ioctx, resp_len)) {
|
||||
PRINT_ERROR("%s[%d]: ch->state= %d tag= %lld",
|
||||
__func__, __LINE__, atomic_read(&ch->state),
|
||||
(unsigned long long)tag);
|
||||
(unsigned long long)scst_cmd_get_tag(scmnd));
|
||||
ret = SCST_TGT_RES_FATAL_ERROR;
|
||||
}
|
||||
|
||||
@@ -2554,9 +2619,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the SCST core to inform ib_srpt that a received task management
|
||||
* function has been completed. Must not block.
|
||||
/**
|
||||
* srpt_tsk_mgmt_done() - SCST callback function that sends back the response
|
||||
* for a task management request.
|
||||
*
|
||||
* Must not block.
|
||||
*/
|
||||
static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,19 @@ enum {
|
||||
SRP_RDMA_READ_FROM_IOC = 0x08,
|
||||
SRP_RDMA_WRITE_FROM_IOC = 0x20,
|
||||
|
||||
/*
|
||||
* srp_cmd::sol_nt / srp_tsk_mgmt::sol_not bitmasks. See also tables
|
||||
* 18 and 20 in the T10 r16a document.
|
||||
*/
|
||||
SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
|
||||
SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
|
||||
|
||||
/*
|
||||
* srp_rsp::sol_not / srp_t_logout::sol_not bitmasks. See also tables
|
||||
* 16 and 22 in the T10 r16a document.
|
||||
*/
|
||||
SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
|
||||
|
||||
/* See also table 24 in the T10 r16a document. */
|
||||
SRP_TSK_MGMT_SUCCESS = 0x00,
|
||||
SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
|
||||
@@ -138,13 +151,13 @@ struct srpt_ioctx {
|
||||
u16 n_rdma_ius;
|
||||
u8 n_rdma;
|
||||
u8 n_rbuf;
|
||||
u8 sol_not;
|
||||
|
||||
enum ib_wc_opcode op;
|
||||
/* Node for insertion in the srpt_thread::thread_ioctx_list. */
|
||||
struct list_head comp_list;
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct scst_cmd *scmnd;
|
||||
u64 data_len;
|
||||
atomic_t state; /*enum srpt_command_state*/
|
||||
};
|
||||
|
||||
@@ -174,6 +187,7 @@ struct srpt_rdma_ch {
|
||||
u8 i_port_id[16];
|
||||
/* 128-bit target port identifier copied from SRP_LOGIN_REQ. */
|
||||
u8 t_port_id[16];
|
||||
int max_ti_iu_len;
|
||||
atomic_t req_lim_delta;
|
||||
atomic_t state; /*enum rdma_ch_state*/
|
||||
/* Node for insertion in the srpt_device::rch_list list. */
|
||||
@@ -244,36 +258,4 @@ struct srpt_device {
|
||||
struct scst_tgt *scst_tgt;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sense code/qualifier pairs (sense_data::key) as defined in the SCSI Primary
|
||||
* Commands (SPC) standard. Bits 0 .. 3 contain the sense key, bit 4 is
|
||||
* reserved, bit 5 is the ILI (incorrect length indicator) bit, bit 6 is the
|
||||
* EOM (end-of-medium) bit and bit 7 is the
|
||||
* FILEMARK bit.
|
||||
*/
|
||||
enum {
|
||||
NO_ADD_SENSE = 0x00,
|
||||
LUN_NOT_READY = 0x04, /* HARDWARE ERROR */
|
||||
INVALID_CDB = 0x24, /* ILI | HARDWARE ERROR */
|
||||
INTERNAL_TARGET_FAILURE = 0x44 /* EOM | HARDWARE ERROR */
|
||||
};
|
||||
|
||||
/*
|
||||
* Sense data structure containing three sense bytes. See also the SCSI Primary
|
||||
* Commands (SPC) standard.
|
||||
*/
|
||||
struct sense_data {
|
||||
u8 err_code;
|
||||
u8 segment_number;
|
||||
u8 key;
|
||||
u8 info_bytes[4];
|
||||
u8 addl_sense_len;
|
||||
u8 cmd_info_bytes[4];
|
||||
u8 addl_sense_code;
|
||||
u8 addl_sense_code_qual;
|
||||
u16 asc_ascq;
|
||||
u8 fru_code;
|
||||
u8 sense_bytes[3];
|
||||
};
|
||||
|
||||
#endif /* IB_SRPT_H */
|
||||
|
||||
Reference in New Issue
Block a user