Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9474b043 authored by Nicholas Bellinger's avatar Nicholas Bellinger
Browse files

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: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent ffe00675
Loading
Loading
Loading
Loading
+52 −70
Original line number Diff line number Diff line
@@ -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,12 +1429,14 @@ 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);
	}
}

/**
 * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
@@ -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);
		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;
		}
	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;
	}

	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);
}

/**
+0 −1
Original line number Diff line number Diff line
@@ -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;