- Updated copyright statement.
- Micro-optimized the function srpt_req_lim_delta().
- Made sure that SRPT does not cause a lockup in (at least) the Linux SRP
  initiator. See also http://bugzilla.kernel.org/show_bug.cgi?id=14235.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1470 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2010-01-14 20:35:37 +00:00
parent 3d9011443c
commit c654261e03

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
* Copyright (C) 2008 Vladislav Bolkhovitin <vst@vlnb.net>
* Copyright (C) 2008 - 2009 Bart Van Assche <bart.vanassche@gmail.com>
* Copyright (C) 2008 - 2010 Bart Van Assche <bart.vanassche@gmail.com>
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -1025,12 +1025,11 @@ out:
static int srpt_req_lim_delta(struct srpt_rdma_ch *ch)
{
int req_lim;
int req_lim_delta;
int last_rsp_req_lim;
req_lim = atomic_read(&ch->req_lim);
req_lim_delta = req_lim - atomic_read(&ch->last_response_req_lim);
atomic_add(req_lim_delta, &ch->last_response_req_lim);
return req_lim_delta;
last_rsp_req_lim = atomic_xchg(&ch->last_response_req_lim, req_lim);
return req_lim - last_rsp_req_lim;
}
static void srpt_reset_ioctx(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
@@ -2594,6 +2593,20 @@ out:
return ret;
}
/**
* srpt_must_wait_for_cred() - Whether or not the target must wait with
* sending a response towards the initiator in order to avoid that the
* initiator locks up. Since an initiator must not send an SRP_CMD request
* when its req_lim variable is less than 2, and since sending a response to
* the initiator will make its req_lim variable equal to ch->req_lim, do not
* send a response to the initiator that would make its req_lim variable less
* than 2.
*/
static inline bool srpt_must_wait_for_cred(struct srpt_rdma_ch *ch)
{
return atomic_read(&ch->req_lim) < 2;
}
/**
* srpt_xmit_response() - SCST callback function that transmits the response
* to a SCSI command.
@@ -2623,6 +2636,17 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
goto out;
}
if (srpt_must_wait_for_cred(ch)) {
if (scst_cmd_atomic(scmnd)) {
TRACE_DBG("%s", "Switching to thread context.");
ret = SCST_TGT_RES_NEED_THREAD_CTX;
goto out;
}
while (srpt_must_wait_for_cred(ch))
schedule();
}
if (srpt_set_cmd_state(ioctx, SRPT_STATE_PROCESSED)
== SRPT_STATE_ABORTED) {
ret = SCST_TGT_RES_SUCCESS;
@@ -2691,6 +2715,9 @@ static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
__func__, (unsigned long long)mgmt_ioctx->tag,
scst_mgmt_cmd_get_status(mcmnd));
if (atomic_read(&ch->req_lim) < 1)
PRINT_ERROR("%s", "Initiator may lock up !!");
if (srpt_set_cmd_state(ioctx, SRPT_STATE_PROCESSED)
== SRPT_STATE_ABORTED)
goto out;