ib_srpt: Convert I/O path to target_submit_cmd + drop legacy ioctx->kref

This patch converts the main srpt_handle_cmd() I/O path to use modern
target_submit_cmd() with TARGET_SCF_ACK_KREF flag usage.  This includes
dropping the original internal ioctx->kref + srpt_put_send_ioctx() usage
in favor of target_put_sess_cmd() w/ se_cmd_t->cmd_kref within ib_srpt
response callbacks.

It also updates srpt_abort_cmd() to call target_put_sess_cmd() for
completion of aborted commands, and adds target_wait_for_sess_cmds() into
srpt_release_channel_work() to allow outstanding I/O to complete during
session shutdown.

Also, go ahead and update srpt_handle_tsk_mgmt() to make the remaining
transport_init_se_cmd() to setup the ioctx->cmd with se_tmr_req.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Bart Van Assche <bvanassche@acm.org>
Cc: Roland Dreier <roland@kernel.org>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Nicholas Bellinger 2012-11-27 23:55:57 -08:00
parent ffe0067544
commit 9474b04313
2 changed files with 52 additions and 71 deletions

View File

@ -1269,7 +1269,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
return ioctx;
BUG_ON(ioctx->ch != ch);
kref_init(&ioctx->kref);
spin_lock_init(&ioctx->spinlock);
ioctx->state = SRPT_STATE_NEW;
ioctx->n_rbuf = 0;
@ -1290,39 +1289,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
return ioctx;
}
/**
* srpt_put_send_ioctx() - Free up resources.
*/
static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
{
struct srpt_rdma_ch *ch;
unsigned long flags;
BUG_ON(!ioctx);
ch = ioctx->ch;
BUG_ON(!ch);
WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
transport_generic_free_cmd(&ioctx->cmd, 0);
if (ioctx->n_rbuf > 1) {
kfree(ioctx->rbufs);
ioctx->rbufs = NULL;
ioctx->n_rbuf = 0;
}
spin_lock_irqsave(&ch->spinlock, flags);
list_add(&ioctx->free_list, &ch->free_list);
spin_unlock_irqrestore(&ch->spinlock, flags);
}
static void srpt_put_send_ioctx_kref(struct kref *kref)
{
srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref));
}
/**
* srpt_abort_cmd() - Abort a SCSI command.
* @ioctx: I/O context associated with the SCSI command.
@ -1359,8 +1325,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
}
spin_unlock_irqrestore(&ioctx->spinlock, flags);
if (state == SRPT_STATE_DONE)
if (state == SRPT_STATE_DONE) {
struct srpt_rdma_ch *ch = ioctx->ch;
BUG_ON(ch->sess == NULL);
target_put_sess_cmd(ch->sess, &ioctx->cmd);
goto out;
}
pr_debug("Aborting cmd with state %d and tag %lld\n", state,
ioctx->tag);
@ -1395,11 +1367,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags);
ioctx->cmd.transport_state |= CMD_T_LUN_STOP;
spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags);
kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
break;
case SRPT_STATE_MGMT_RSP_SENT:
srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
break;
default:
WARN_ON("ERROR: unexpected command state");
@ -1457,11 +1429,13 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
&& state != SRPT_STATE_DONE))
pr_debug("state = %d\n", state);
if (state != SRPT_STATE_DONE)
kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
else
if (state != SRPT_STATE_DONE) {
srpt_unmap_sg_to_ib_sge(ch, ioctx);
transport_generic_free_cmd(&ioctx->cmd, 0);
} else {
printk(KERN_ERR "IB completion has been received too late for"
" wr_id = %u.\n", ioctx->ioctx.index);
}
}
/**
@ -1712,10 +1686,10 @@ out_err:
static int srpt_check_stop_free(struct se_cmd *cmd)
{
struct srpt_send_ioctx *ioctx;
struct srpt_send_ioctx *ioctx = container_of(cmd,
struct srpt_send_ioctx, cmd);
ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
}
/**
@ -1731,11 +1705,11 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
u64 data_len;
enum dma_data_direction dir;
sense_reason_t ret;
int rc;
BUG_ON(!send_ioctx);
srp_cmd = recv_ioctx->ioctx.buf;
kref_get(&send_ioctx->kref);
cmd = &send_ioctx->cmd;
send_ioctx->tag = srp_cmd->tag;
@ -1759,30 +1733,18 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
srp_cmd->tag);
ret = TCM_INVALID_CDB_FIELD;
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
goto send_sense;
}
cmd->data_length = data_len;
cmd->data_direction = dir;
unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
sizeof(srp_cmd->lun));
ret = transport_lookup_cmd_lun(cmd, unpacked_lun);
if (ret) {
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
rc = target_submit_cmd(cmd, ch->sess, srp_cmd->cdb,
&send_ioctx->sense_data[0], unpacked_lun, data_len,
MSG_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF);
if (rc != 0) {
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto send_sense;
}
ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb);
if (ret) {
kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
if (ret == TCM_RESERVATION_CONFLICT) {
srpt_queue_status(cmd);
return 0;
}
goto send_sense;
}
transport_handle_cdb_direct(cmd);
return 0;
send_sense:
@ -1884,6 +1846,9 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
goto fail;
}
transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,
0, DMA_NONE, MSG_SIMPLE_TAG, send_ioctx->sense_data);
res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
if (res < 0) {
send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
@ -1902,11 +1867,9 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
kref_get(&send_ioctx->kref);
transport_generic_handle_tmr(&send_ioctx->cmd);
return;
fail:
kref_get(&send_ioctx->kref);
transport_send_check_condition_and_sense(cmd, 0, 0); // XXX:
}
@ -1949,10 +1912,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
}
}
transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,
0, DMA_NONE, MSG_SIMPLE_TAG,
send_ioctx->sense_data);
switch (srp_cmd->opcode) {
case SRP_CMD:
srpt_handle_cmd(ch, recv_ioctx, send_ioctx);
@ -2358,6 +2317,7 @@ static void srpt_release_channel_work(struct work_struct *w)
{
struct srpt_rdma_ch *ch;
struct srpt_device *sdev;
struct se_session *se_sess;
ch = container_of(w, struct srpt_rdma_ch, release_work);
pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess,
@ -2366,8 +2326,13 @@ static void srpt_release_channel_work(struct work_struct *w)
sdev = ch->sport->sdev;
BUG_ON(!sdev);
transport_deregister_session_configfs(ch->sess);
transport_deregister_session(ch->sess);
se_sess = ch->sess;
BUG_ON(!se_sess);
target_wait_for_sess_cmds(se_sess, 0);
transport_deregister_session_configfs(se_sess);
transport_deregister_session(se_sess);
ch->sess = NULL;
srpt_destroy_ch_ib(ch);
@ -3092,7 +3057,7 @@ static int srpt_queue_response(struct se_cmd *cmd)
ioctx->tag);
srpt_unmap_sg_to_ib_sge(ch, ioctx);
srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
}
out:
@ -3483,6 +3448,23 @@ static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)
static void srpt_release_cmd(struct se_cmd *se_cmd)
{
struct srpt_send_ioctx *ioctx = container_of(se_cmd,
struct srpt_send_ioctx, cmd);
struct srpt_rdma_ch *ch = ioctx->ch;
unsigned long flags;
WARN_ON(ioctx->state != SRPT_STATE_DONE);
WARN_ON(ioctx->mapped_sg_count != 0);
if (ioctx->n_rbuf > 1) {
kfree(ioctx->rbufs);
ioctx->rbufs = NULL;
ioctx->n_rbuf = 0;
}
spin_lock_irqsave(&ch->spinlock, flags);
list_add(&ioctx->free_list, &ch->free_list);
spin_unlock_irqrestore(&ch->spinlock, flags);
}
/**

View File

@ -228,7 +228,6 @@ struct srpt_recv_ioctx {
struct srpt_send_ioctx {
struct srpt_ioctx ioctx;
struct srpt_rdma_ch *ch;
struct kref kref;
struct rdma_iu *rdma_ius;
struct srp_direct_buf *rbufs;
struct srp_direct_buf single_rbuf;