- Bug fix: if processing of any of the SRP task management functions by

the SCST core fails (abort task, LUN reset, ...), an SRP_RSP PDU is
  now sent back to the initiator.
- Added more debug tracing statements.
- Improved readability of some parts of the source code.
- Added more comments.
- Partially reverted one hunk of r1003: while casting an unsigned 64-bit
  value to the type u64 and printing such values via %llx works fine on
  x86 systems, the same code triggers a compiler warning on PowerPC
  systems. So while r1003 changed some (unsigned long long) casts to (u64)
  casts, this revision changes these back to (unsigned long long) casts.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1012 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2009-08-04 18:45:46 +00:00
parent b06a932d2c
commit 6dc8835e7e

View File

@@ -654,7 +654,12 @@ static int srpt_post_recv(struct srpt_device *sdev, struct srpt_ioctx *ioctx)
}
/*
* Post a send request on the SRPT RDMA channel 'ch'.
* Post an IB send request.
* @ch: RDMA channel to post the send request on.
* @ioctx: I/O context of the send request.
* @len: length of the request to be sent in bytes.
*
* Returns zero upon success and a non-zero value upon failure.
*/
static int srpt_post_send(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx,
int len)
@@ -881,6 +886,18 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
scst_estimate_context());
}
/**
* Build an SRP_RSP response PDU.
* @ch: RDMA channel through which the request has been received.
* @ioctx: I/O context in which the SRP_RSP PDU 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.
* @tag: tag of the request for which this response is being generated.
*
* An SRP_RSP PDU contains a SCSI status or service response. See also
* section 6.9 in the T10 SRP r16a document for the format of an SRP_RSP PDU.
* See also SPC-2 for more information about sense data.
*/
static void srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
struct srpt_ioctx *ioctx, u8 s_key, u8 s_code,
u64 tag)
@@ -944,30 +961,30 @@ static void srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
*/
static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
{
struct scst_cmd *scmnd = NULL;
struct srp_cmd *srp_cmd = NULL;
struct scst_cmd *scmnd;
struct srp_cmd *srp_cmd;
struct srp_rsp *srp_rsp;
scst_data_direction dir = SCST_DATA_NONE;
int indirect_desc = 0;
int ret;
unsigned long flags;
srp_cmd = ioctx->buf;
srp_rsp = ioctx->buf;
if (srp_cmd->buf_fmt) {
ret = srpt_get_desc_tbl(ioctx, srp_cmd, &indirect_desc);
if (ret) {
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
NO_ADD_SENSE, srp_cmd->tag);
((struct srp_rsp *)ioctx->buf)->status =
SAM_STAT_TASK_SET_FULL;
srp_rsp->status = SAM_STAT_TASK_SET_FULL;
goto send_rsp;
}
if (indirect_desc) {
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
NO_ADD_SENSE, srp_cmd->tag);
((struct srp_rsp *)ioctx->buf)->status =
SAM_STAT_TASK_SET_FULL;
srp_rsp->status = SAM_STAT_TASK_SET_FULL;
goto send_rsp;
}
@@ -986,8 +1003,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
if (!scmnd) {
srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
NO_ADD_SENSE, srp_cmd->tag);
((struct srp_rsp *)ioctx->buf)->status =
SAM_STAT_TASK_SET_FULL;
srp_rsp->status = SAM_STAT_TASK_SET_FULL;
goto send_rsp;
}
@@ -1029,12 +1045,25 @@ send_rsp:
}
/*
* Process SRP_TSK_MGMT. See also table 19 in the T10 SRP r16a document.
* Process an SRP_TSK_MGMT request PDU.
*
* Returns 0 upon success and -1 upon failure.
*
* Each task management function is performed by calling one of the
* scst_rx_mgmt_fn*() functions. These functions will either report failure
* or process the task management function asynchronously. The function
* srpt_tsk_mgmt_done() will be called by the SCST core upon completion of the
* task management function. When srpt_handle_tsk_mgmt() reports failure
* (i.e. returns -1) a response PDU will have been built in ioctx->buf. This
* PDU has to be sent back by the caller.
*
* For more information about SRP_TSK_MGMT PDU's, 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)
{
struct srp_tsk_mgmt *srp_tsk = NULL;
struct srp_tsk_mgmt *srp_tsk;
struct srpt_mgmt_ioctx *mgmt_ioctx;
int ret;
@@ -1051,7 +1080,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
if (!mgmt_ioctx) {
srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED,
srp_tsk->tag);
goto send_rsp;
goto err;
}
mgmt_ioctx->ioctx = ioctx;
@@ -1060,6 +1089,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
switch (srp_tsk->tsk_mgmt_func) {
case SRP_TSK_ABORT_TASK:
TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK");
ret = scst_rx_mgmt_fn_tag(ch->scst_sess,
SCST_ABORT_TASK,
srp_tsk->task_tag,
@@ -1068,6 +1098,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
mgmt_ioctx);
break;
case SRP_TSK_ABORT_TASK_SET:
TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK_SET");
ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
SCST_ABORT_TASK_SET,
(u8 *) &srp_tsk->lun,
@@ -1077,6 +1108,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
mgmt_ioctx);
break;
case SRP_TSK_CLEAR_TASK_SET:
TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_TASK_SET");
ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
SCST_CLEAR_TASK_SET,
(u8 *) &srp_tsk->lun,
@@ -1086,6 +1118,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
mgmt_ioctx);
break;
case SRP_TSK_LUN_RESET:
TRACE_DBG("%s", "Processing SRP_TSK_LUN_RESET");
ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
SCST_LUN_RESET,
(u8 *) &srp_tsk->lun,
@@ -1095,6 +1128,7 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
mgmt_ioctx);
break;
case SRP_TSK_CLEAR_ACA:
TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_ACA");
ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
SCST_CLEAR_ACA,
(u8 *) &srp_tsk->lun,
@@ -1104,22 +1138,38 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
mgmt_ioctx);
break;
default:
TRACE_DBG("%s", "Unsupported task management function.");
srpt_build_tskmgmt_rsp(ch, ioctx,
SRP_TSK_MGMT_FUNC_NOT_SUPP,
srp_tsk->tag);
goto send_rsp;
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);
goto err;
}
return 0;
send_rsp:
err:
return -1;
}
/**
* Process a receive completion event.
* @ch: RDMA channel for which the completion event has been received.
* @ioctx: SRPT I/O context for which the completion event has been received.
*/
static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
struct srpt_ioctx *ioctx)
{
u8 op;
struct srp_cmd *srp_cmd;
struct srp_rsp *srp_rsp;
unsigned long flags;
int len;
if (ch->state != RDMA_CHANNEL_LIVE) {
if (ch->state == RDMA_CHANNEL_CONNECTING) {
@@ -1143,25 +1193,26 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
ioctx->rdma_ius = NULL;
ioctx->scmnd = NULL;
op = *(u8 *) ioctx->buf;
switch (op) {
srp_cmd = ioctx->buf;
srp_rsp = ioctx->buf;
switch (srp_cmd->opcode) {
case SRP_CMD:
if (srpt_handle_cmd(ch, ioctx) < 0)
goto send_rsp;
goto err;
break;
case SRP_TSK_MGMT:
if (srpt_handle_tsk_mgmt(ch, ioctx) < 0)
goto send_rsp;
goto err;
break;
case SRP_I_LOGOUT:
case SRP_AER_REQ:
default:
srpt_build_cmd_rsp(ch, ioctx, ILLEGAL_REQUEST, INVALID_CDB,
((struct srp_cmd *)ioctx->buf)->tag);
goto send_rsp;
srp_cmd->tag);
goto err;
}
dma_sync_single_for_device(ch->sport->sdev->device->dma_device,
@@ -1170,13 +1221,15 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
return;
send_rsp:
if (ch->state != RDMA_CHANNEL_LIVE ||
srpt_post_send(ch, ioctx,
sizeof(struct srp_rsp) +
be32_to_cpu(((struct srp_rsp *)ioctx->buf)->
sense_data_len)))
err:
WARN_ON(srp_rsp->opcode != SRP_RSP);
len = (sizeof *srp_rsp) + be32_to_cpu(srp_rsp->sense_data_len);
if (ch->state != RDMA_CHANNEL_LIVE || srpt_post_send(ch, ioctx, len)) {
printk(KERN_ERR PFX "%s: sending SRP_RSP PDU failed",
__func__);
srpt_reset_ioctx(ch, ioctx);
}
}
/*
@@ -1206,9 +1259,11 @@ static inline void srpt_schedule_thread(struct srpt_ioctx *ioctx)
wake_up(&ioctx_list_waitQ);
}
/*
* InfiniBand CQ (completion queue) event handler for asynchronous events not
* associated with a completion.
/**
* InfiniBand completion queue callback function.
* @cq: completion queue.
* @ctx: completion queue context, which was passed as the fourth argument of
* the function ib_create_cq().
*/
static void srpt_completion(struct ib_cq *cq, void *ctx)
{
@@ -1451,12 +1506,12 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
it_iu_len = be32_to_cpu(req->req_it_iu_len);
TRACE_DBG("Host login i_port_id=0x%llx:0x%llx t_port_id=0x%llx:0x%llx"
" it_iu_len=%d",
(u64)be64_to_cpu(*(u64 *)&req->initiator_port_id[0]),
(u64)be64_to_cpu(*(u64 *)&req->initiator_port_id[8]),
(u64)be64_to_cpu(*(u64 *)&req->target_port_id[0]),
(u64)be64_to_cpu(*(u64 *)&req->target_port_id[8]),
it_iu_len);
" it_iu_len=%d",
(unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[0]),
(unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[8]),
(unsigned long long)be64_to_cpu(*(u64 *)&req->target_port_id[0]),
(unsigned long long)be64_to_cpu(*(u64 *)&req->target_port_id[8]),
it_iu_len);
if (it_iu_len > MAX_MESSAGE_SIZE || it_iu_len < 64) {
rej->reason =