mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-19 21:56:31 +00:00
- Small performance improvement: ib_dma_sync_for_device() and
ib_dma_sync_for_cpu() calls do now only synchronize the data areas used. - Removed per-command mutex again because it's not a full solution with regard to avoiding races between module unloading / IB error handling and SCST's command handling. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1335 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+72
-60
@@ -636,7 +636,7 @@ static void srpt_unregister_mad_agent(struct srpt_device *sdev)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Allocate and initialize an SRPT I/O context structure.
|
||||
*/
|
||||
static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev)
|
||||
@@ -735,7 +735,6 @@ static enum srpt_command_state srpt_set_cmd_state(struct srpt_ioctx *ioctx,
|
||||
enum srpt_command_state previous;
|
||||
|
||||
WARN_ON(!ioctx);
|
||||
WARN_ON(!mutex_is_locked(&ioctx->mutex));
|
||||
WARN_ON(new == SRPT_STATE_NEW);
|
||||
|
||||
previous = ioctx->state;
|
||||
@@ -760,7 +759,6 @@ srpt_test_and_set_cmd_state(struct srpt_ioctx *ioctx,
|
||||
enum srpt_command_state previous;
|
||||
|
||||
WARN_ON(!ioctx);
|
||||
WARN_ON(!mutex_is_locked(&ioctx->mutex));
|
||||
WARN_ON(expected == SRPT_STATE_ABORTED);
|
||||
WARN_ON(new == SRPT_STATE_NEW);
|
||||
|
||||
@@ -771,7 +769,7 @@ srpt_test_and_set_cmd_state(struct srpt_ioctx *ioctx,
|
||||
return previous;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Post a receive request on the work queue of InfiniBand device 'sdev'.
|
||||
*/
|
||||
static int srpt_post_recv(struct srpt_device *sdev, struct srpt_ioctx *ioctx)
|
||||
@@ -792,7 +790,7 @@ static int srpt_post_recv(struct srpt_device *sdev, struct srpt_ioctx *ioctx)
|
||||
return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Post an IB send request.
|
||||
* @ch: RDMA channel to post the send request on.
|
||||
* @ioctx: I/O context of the send request.
|
||||
@@ -808,7 +806,7 @@ static int srpt_post_send(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx,
|
||||
struct srpt_device *sdev = ch->sport->sdev;
|
||||
|
||||
ib_dma_sync_single_for_device(sdev->device, ioctx->dma,
|
||||
srp_max_message_size, DMA_TO_DEVICE);
|
||||
len, DMA_TO_DEVICE);
|
||||
|
||||
list.addr = ioctx->dma;
|
||||
list.length = len;
|
||||
@@ -836,6 +834,10 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd,
|
||||
ioctx->n_rbuf = 1;
|
||||
ioctx->rbufs = &ioctx->single_rbuf;
|
||||
|
||||
ib_dma_sync_single_for_cpu(ioctx->ch->sport->sdev->device,
|
||||
ioctx->dma + sizeof(struct srp_cmd),
|
||||
sizeof(*db), DMA_FROM_DEVICE);
|
||||
|
||||
db = (void *)srp_cmd->add_data;
|
||||
memcpy(ioctx->rbufs, db, sizeof *db);
|
||||
ioctx->data_len = be32_to_cpu(db->len);
|
||||
@@ -861,6 +863,11 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ib_dma_sync_single_for_cpu(ioctx->ch->sport->sdev->device,
|
||||
ioctx->dma + sizeof(struct srp_cmd),
|
||||
ioctx->n_rbuf * sizeof(*db),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
db = idb->desc_list;
|
||||
memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
|
||||
ioctx->data_len = be32_to_cpu(idb->len);
|
||||
@@ -983,9 +990,7 @@ static void srpt_reset_ioctx(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort a command. Must be called from inside rdy_to_xfer, xmit_response or
|
||||
* on_free_cmd because any call from outside SCST's command processing callback
|
||||
* functions would be racy.
|
||||
* Abort a command.
|
||||
*/
|
||||
static void srpt_abort_scst_cmd(struct srpt_device *sdev,
|
||||
struct scst_cmd *scmnd)
|
||||
@@ -997,8 +1002,6 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev,
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
previous_state = srpt_set_cmd_state(ioctx, SRPT_STATE_ABORTED);
|
||||
if (previous_state == SRPT_STATE_ABORTED)
|
||||
goto out;
|
||||
@@ -1034,7 +1037,27 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev,
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort an SCST command if the channel is has been disconnected.
|
||||
*
|
||||
* Returns true if the command has been aborted because the channel is
|
||||
* disconnecting, and false if the channel is not being disconnected.
|
||||
* Must be called from inside rdy_to_xfer, xmit_response or on_free_cmd
|
||||
* because any call from outside SCST's command processing callback functions
|
||||
* would be racy.
|
||||
*/
|
||||
static bool srpt_abort_if_disconnecting(struct srpt_ioctx *ioctx)
|
||||
{
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
if (ioctx->ch->state == RDMA_CHANNEL_DISCONNECTING) {
|
||||
srpt_abort_scst_cmd(ioctx->ch->sport->sdev, ioctx->scmnd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc)
|
||||
@@ -1085,8 +1108,6 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
/*
|
||||
* If an RDMA completion notification has been received for a write
|
||||
* command, tell SCST that processing can continue by calling
|
||||
@@ -1099,8 +1120,6 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
|
||||
scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS,
|
||||
scst_estimate_context());
|
||||
}
|
||||
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1124,7 +1143,12 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
|
||||
struct srp_rsp *srp_rsp;
|
||||
struct sense_data *sense;
|
||||
int limit_delta;
|
||||
int sense_data_len = 0;
|
||||
int sense_data_len;
|
||||
int resp_len;
|
||||
|
||||
sense_data_len = (s_key == NO_SENSE) ? 0
|
||||
: sizeof(*sense) + sizeof(*sense) % 4;
|
||||
resp_len = sizeof(*srp_rsp) + sense_data_len;
|
||||
|
||||
srp_rsp = ioctx->buf;
|
||||
memset(srp_rsp, 0, sizeof *srp_rsp);
|
||||
@@ -1137,7 +1161,6 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
|
||||
srp_rsp->tag = tag;
|
||||
|
||||
if (s_key != NO_SENSE) {
|
||||
sense_data_len = sizeof *sense + (sizeof *sense % 4);
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
|
||||
srp_rsp->status = SAM_STAT_CHECK_CONDITION;
|
||||
srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
|
||||
@@ -1148,7 +1171,7 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
|
||||
sense->asc_ascq = s_code;
|
||||
}
|
||||
|
||||
return sizeof(*srp_rsp) + sense_data_len;
|
||||
return resp_len;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1170,10 +1193,11 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
|
||||
{
|
||||
struct srp_rsp *srp_rsp;
|
||||
int limit_delta;
|
||||
int resp_data_len = 0;
|
||||
int resp_data_len;
|
||||
int resp_len;
|
||||
|
||||
ib_dma_sync_single_for_cpu(ch->sport->sdev->device, ioctx->dma,
|
||||
srp_max_message_size, DMA_TO_DEVICE);
|
||||
resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
|
||||
resp_len = sizeof(*srp_rsp) + resp_data_len;
|
||||
|
||||
srp_rsp = ioctx->buf;
|
||||
memset(srp_rsp, 0, sizeof *srp_rsp);
|
||||
@@ -1186,13 +1210,12 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
|
||||
srp_rsp->tag = tag;
|
||||
|
||||
if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
|
||||
resp_data_len = 4;
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
|
||||
srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
|
||||
srp_rsp->data[3] = rsp_code;
|
||||
}
|
||||
|
||||
return sizeof(*srp_rsp) + resp_data_len;
|
||||
return resp_len;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1313,6 +1336,10 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
||||
struct srpt_mgmt_ioctx *mgmt_ioctx;
|
||||
int ret;
|
||||
|
||||
ib_dma_sync_single_for_cpu(ch->sport->sdev->device, ioctx->dma,
|
||||
sizeof(struct srp_tsk_mgmt),
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
srp_tsk = ioctx->buf;
|
||||
|
||||
TRACE_DBG("recv_tsk_mgmt= %d for task_tag= %lld"
|
||||
@@ -1437,9 +1464,8 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
|
||||
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||
|
||||
ib_dma_sync_single_for_cpu(ch->sport->sdev->device, ioctx->dma,
|
||||
srp_max_message_size, DMA_FROM_DEVICE);
|
||||
sizeof(struct srp_cmd), DMA_FROM_DEVICE);
|
||||
|
||||
mutex_init(&ioctx->mutex);
|
||||
ioctx->data_len = 0;
|
||||
ioctx->n_rbuf = 0;
|
||||
ioctx->rbufs = NULL;
|
||||
@@ -1472,10 +1498,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ib_dma_sync_single_for_device(ch->sport->sdev->device,
|
||||
ioctx->dma, srp_max_message_size,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
@@ -1684,6 +1706,8 @@ static struct srpt_rdma_ch *srpt_find_channel(struct ib_cm_id *cm_id, bool del)
|
||||
*/
|
||||
static void srpt_release_channel(struct srpt_rdma_ch *ch, bool destroy_cmid)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
WARN_ON(srpt_find_channel(ch->cm_id, false) == ch);
|
||||
@@ -1713,20 +1737,20 @@ static void srpt_release_channel(struct srpt_rdma_ch *ch, bool destroy_cmid)
|
||||
else
|
||||
PRINT_INFO("Releasing session %s", ch->sess_name);
|
||||
|
||||
spin_lock_irq(&ch->spinlock);
|
||||
spin_lock_irqsave(&ch->spinlock, flags);
|
||||
list_for_each_entry_safe(ioctx, ioctx_tmp,
|
||||
&ch->active_scmnd_list, scmnd_list) {
|
||||
spin_unlock_irq(&ch->spinlock);
|
||||
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||
|
||||
if (ioctx->scmnd)
|
||||
srpt_abort_scst_cmd(ch->sport->sdev,
|
||||
ioctx->scmnd);
|
||||
|
||||
spin_lock_irq(&ch->spinlock);
|
||||
spin_lock_irqsave(&ch->spinlock, flags);
|
||||
}
|
||||
WARN_ON(!list_empty(&ch->active_scmnd_list));
|
||||
WARN_ON(ch->active_scmnd_cnt != 0);
|
||||
spin_unlock_irq(&ch->spinlock);
|
||||
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||
|
||||
scst_unregister_session(ch->scst_sess, 0, NULL);
|
||||
ch->scst_sess = NULL;
|
||||
@@ -2416,10 +2440,9 @@ static int srpt_rdy_to_xfer(struct scst_cmd *scmnd)
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
if (srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA)
|
||||
== SRPT_STATE_ABORTED) {
|
||||
== SRPT_STATE_ABORTED
|
||||
|| srpt_abort_if_disconnecting(ioctx)) {
|
||||
TRACE_DBG("cmd with tag %lld has been aborted",
|
||||
scst_cmd_get_tag(scmnd));
|
||||
ret = SCST_TGT_RES_FATAL_ERROR;
|
||||
@@ -2442,8 +2465,6 @@ static int srpt_rdy_to_xfer(struct scst_cmd *scmnd)
|
||||
ret = srpt_xfer_data(ch, ioctx, scmnd);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2464,10 +2485,9 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
if (srpt_set_cmd_state(ioctx, SRPT_STATE_PROCESSED)
|
||||
== SRPT_STATE_ABORTED) {
|
||||
== SRPT_STATE_ABORTED
|
||||
|| srpt_abort_if_disconnecting(ioctx)) {
|
||||
TRACE_DBG("cmd with tag %lld has been aborted",
|
||||
scst_cmd_get_tag(scmnd));
|
||||
ret = SCST_TGT_RES_FATAL_ERROR;
|
||||
@@ -2496,11 +2516,6 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ib_dma_sync_single_for_cpu(ch->sport->sdev->device, ioctx->dma,
|
||||
srp_max_message_size, DMA_TO_DEVICE);
|
||||
|
||||
srp_rsp = ioctx->buf;
|
||||
|
||||
if (unlikely(scst_cmd_aborted(scmnd))) {
|
||||
TRACE_MGMT_DBG("%s: tag= %lld already got aborted",
|
||||
__func__, (unsigned long long)tag);
|
||||
@@ -2512,6 +2527,8 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
|
||||
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))) {
|
||||
srp_rsp->sense_data_len = scst_cmd_get_sense_buffer_len(scmnd);
|
||||
BUILD_BUG_ON(MIN_MAX_MESSAGE_SIZE <= sizeof(*srp_rsp));
|
||||
@@ -2554,14 +2571,12 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
return ret;
|
||||
|
||||
out_aborted:
|
||||
ret = SCST_TGT_RES_SUCCESS;
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
srpt_abort_scst_cmd(ch->sport->sdev, scmnd);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2584,14 +2599,13 @@ static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
|
||||
ioctx = mgmt_ioctx->ioctx;
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
TRACE_DBG("%s: tsk_mgmt_done for tag= %lld status=%d",
|
||||
__func__, (unsigned long long)mgmt_ioctx->tag,
|
||||
scst_mgmt_cmd_get_status(mcmnd));
|
||||
|
||||
if (srpt_set_cmd_state(ioctx, SRPT_STATE_PROCESSED)
|
||||
== SRPT_STATE_ABORTED)
|
||||
== SRPT_STATE_ABORTED
|
||||
|| srpt_abort_if_disconnecting(ioctx))
|
||||
goto out;
|
||||
|
||||
rsp_len = srpt_build_tskmgmt_rsp(ch, ioctx,
|
||||
@@ -2607,7 +2621,7 @@ static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
|
||||
kfree(mgmt_ioctx);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2618,24 +2632,22 @@ static void srpt_on_free_cmd(struct scst_cmd *scmnd)
|
||||
{
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct srpt_ioctx *ioctx;
|
||||
unsigned long flags;
|
||||
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
|
||||
mutex_lock(&ioctx->mutex);
|
||||
|
||||
srpt_set_cmd_state(ioctx, SRPT_STATE_ABORTED);
|
||||
ch = ioctx->ch;
|
||||
BUG_ON(!ch);
|
||||
spin_lock_irq(&ch->spinlock);
|
||||
spin_lock_irqsave(&ch->spinlock, flags);
|
||||
list_del(&ioctx->scmnd_list);
|
||||
ch->active_scmnd_cnt--;
|
||||
spin_unlock_irq(&ch->spinlock);
|
||||
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||
ioctx->ch = NULL;
|
||||
|
||||
srpt_reset_ioctx(ch, ioctx);
|
||||
scst_cmd_set_tgt_priv(scmnd, NULL);
|
||||
|
||||
mutex_unlock(&ioctx->mutex);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) && ! defined(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19)
|
||||
|
||||
@@ -121,7 +121,6 @@ enum srpt_command_state {
|
||||
|
||||
/* SRPT I/O context: SRPT-private data associated with a struct scst_cmd. */
|
||||
struct srpt_ioctx {
|
||||
struct mutex mutex;
|
||||
int index;
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
|
||||
Reference in New Issue
Block a user