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

Commit c91d7072 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target fixes from Nicholas Bellinger:
 "This includes a iser-target series from Jenny + Sagi @ Mellanox that
  addresses the few remaining active I/O shutdown bugs, along with a
  patch to support zero-copy for immediate data payloads that gives a
  nice performance improvement for small block WRITEs.

  Also included are some recent >= v4.2 regression bug-fixes.  The most
  notable is a RCU conversion regression for SPC-3 PR registrations, and
  recent removal of obsolete RFC-3720 markers that introduced a login
  regression bug with MSFT iSCSI initiators.

  Thanks to everyone who has been testing + reporting bugs for v4.x"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  iscsi-target: Avoid OFMarker + IFMarker negotiation
  target: Make TCM_WRITE_PROTECT failure honor D_SENSE bit
  target: Fix target_sense_desc_format NULL pointer dereference
  target: Propigate backend read-only to core_tpg_add_lun
  target: Fix PR registration + APTPL RCU conversion regression
  iser-target: Skip data copy if all the command data comes as immediate
  iser-target: Change the recv buffers posting logic
  iser-target: Fix pending connections handling in target stack shutdown sequnce
  iser-target: Remove np_ prefix from isert_np members
  iser-target: Remove unused variables
  iser-target: Put the reference on commands waiting for unsol data
  iser-target: remove command with state ISTATE_REMOVE
parents bcba282a 673681ca
Loading
Loading
Loading
Loading
+186 −107
Original line number Diff line number Diff line
@@ -238,8 +238,6 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
		rx_sg->lkey = device->pd->local_dma_lkey;
	}

	isert_conn->rx_desc_head = 0;

	return 0;

dma_map_fail:
@@ -634,7 +632,7 @@ static void
isert_init_conn(struct isert_conn *isert_conn)
{
	isert_conn->state = ISER_CONN_INIT;
	INIT_LIST_HEAD(&isert_conn->accept_node);
	INIT_LIST_HEAD(&isert_conn->node);
	init_completion(&isert_conn->login_comp);
	init_completion(&isert_conn->login_req_comp);
	init_completion(&isert_conn->wait);
@@ -762,28 +760,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
	ret = isert_rdma_post_recvl(isert_conn);
	if (ret)
		goto out_conn_dev;
	/*
	 * Obtain the second reference now before isert_rdma_accept() to
	 * ensure that any initiator generated REJECT CM event that occurs
	 * asynchronously won't drop the last reference until the error path
	 * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() ->
	 * isert_free_conn() -> isert_put_conn() -> kref_put().
	 */
	if (!kref_get_unless_zero(&isert_conn->kref)) {
		isert_warn("conn %p connect_release is running\n", isert_conn);
		goto out_conn_dev;
	}

	ret = isert_rdma_accept(isert_conn);
	if (ret)
		goto out_conn_dev;

	mutex_lock(&isert_np->np_accept_mutex);
	list_add_tail(&isert_conn->accept_node, &isert_np->np_accept_list);
	mutex_unlock(&isert_np->np_accept_mutex);
	mutex_lock(&isert_np->mutex);
	list_add_tail(&isert_conn->node, &isert_np->accepted);
	mutex_unlock(&isert_np->mutex);

	isert_info("np %p: Allow accept_np to continue\n", np);
	up(&isert_np->np_sem);
	return 0;

out_conn_dev:
@@ -831,13 +816,21 @@ static void
isert_connected_handler(struct rdma_cm_id *cma_id)
{
	struct isert_conn *isert_conn = cma_id->qp->qp_context;
	struct isert_np *isert_np = cma_id->context;

	isert_info("conn %p\n", isert_conn);

	mutex_lock(&isert_conn->mutex);
	if (isert_conn->state != ISER_CONN_FULL_FEATURE)
	isert_conn->state = ISER_CONN_UP;
	kref_get(&isert_conn->kref);
	mutex_unlock(&isert_conn->mutex);

	mutex_lock(&isert_np->mutex);
	list_move_tail(&isert_conn->node, &isert_np->pending);
	mutex_unlock(&isert_np->mutex);

	isert_info("np %p: Allow accept_np to continue\n", isert_np);
	up(&isert_np->sem);
}

static void
@@ -903,14 +896,14 @@ isert_np_cma_handler(struct isert_np *isert_np,

	switch (event) {
	case RDMA_CM_EVENT_DEVICE_REMOVAL:
		isert_np->np_cm_id = NULL;
		isert_np->cm_id = NULL;
		break;
	case RDMA_CM_EVENT_ADDR_CHANGE:
		isert_np->np_cm_id = isert_setup_id(isert_np);
		if (IS_ERR(isert_np->np_cm_id)) {
		isert_np->cm_id = isert_setup_id(isert_np);
		if (IS_ERR(isert_np->cm_id)) {
			isert_err("isert np %p setup id failed: %ld\n",
				  isert_np, PTR_ERR(isert_np->np_cm_id));
			isert_np->np_cm_id = NULL;
				  isert_np, PTR_ERR(isert_np->cm_id));
			isert_np->cm_id = NULL;
		}
		break;
	default:
@@ -929,7 +922,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
	struct isert_conn *isert_conn;
	bool terminating = false;

	if (isert_np->np_cm_id == cma_id)
	if (isert_np->cm_id == cma_id)
		return isert_np_cma_handler(cma_id->context, event);

	isert_conn = cma_id->qp->qp_context;
@@ -945,13 +938,13 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
	if (terminating)
		goto out;

	mutex_lock(&isert_np->np_accept_mutex);
	if (!list_empty(&isert_conn->accept_node)) {
		list_del_init(&isert_conn->accept_node);
	mutex_lock(&isert_np->mutex);
	if (!list_empty(&isert_conn->node)) {
		list_del_init(&isert_conn->node);
		isert_put_conn(isert_conn);
		queue_work(isert_release_wq, &isert_conn->release_work);
	}
	mutex_unlock(&isert_np->np_accept_mutex);
	mutex_unlock(&isert_np->mutex);

out:
	return 0;
@@ -962,6 +955,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
{
	struct isert_conn *isert_conn = cma_id->qp->qp_context;

	list_del_init(&isert_conn->node);
	isert_conn->cm_id = NULL;
	isert_put_conn(isert_conn);

@@ -1006,22 +1000,19 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
}

static int
isert_post_recv(struct isert_conn *isert_conn, u32 count)
isert_post_recvm(struct isert_conn *isert_conn, u32 count)
{
	struct ib_recv_wr *rx_wr, *rx_wr_failed;
	int i, ret;
	unsigned int rx_head = isert_conn->rx_desc_head;
	struct iser_rx_desc *rx_desc;

	for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
		rx_desc		= &isert_conn->rx_descs[rx_head];
		rx_desc = &isert_conn->rx_descs[i];
		rx_wr->wr_id = (uintptr_t)rx_desc;
		rx_wr->sg_list = &rx_desc->rx_sg;
		rx_wr->num_sge = 1;
		rx_wr->next = rx_wr + 1;
		rx_head = (rx_head + 1) & (ISERT_QP_MAX_RECV_DTOS - 1);
	}

	rx_wr--;
	rx_wr->next = NULL; /* mark end of work requests list */

@@ -1031,10 +1022,29 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
	if (ret) {
		isert_err("ib_post_recv() failed with ret: %d\n", ret);
		isert_conn->post_recv_buf_count -= count;
	} else {
		isert_dbg("Posted %d RX buffers\n", count);
		isert_conn->rx_desc_head = rx_head;
	}

	return ret;
}

static int
isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
{
	struct ib_recv_wr *rx_wr_failed, rx_wr;
	int ret;

	rx_wr.wr_id = (uintptr_t)rx_desc;
	rx_wr.sg_list = &rx_desc->rx_sg;
	rx_wr.num_sge = 1;
	rx_wr.next = NULL;

	isert_conn->post_recv_buf_count++;
	ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
	if (ret) {
		isert_err("ib_post_recv() failed with ret: %d\n", ret);
		isert_conn->post_recv_buf_count--;
	}

	return ret;
}

@@ -1205,7 +1215,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
			if (ret)
				return ret;

			ret = isert_post_recv(isert_conn, ISERT_MIN_POSTED_RX);
			ret = isert_post_recvm(isert_conn,
					       ISERT_QP_MAX_RECV_DTOS);
			if (ret)
				return ret;

@@ -1278,7 +1289,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
}

static struct iscsi_cmd
*isert_allocate_cmd(struct iscsi_conn *conn)
*isert_allocate_cmd(struct iscsi_conn *conn, struct iser_rx_desc *rx_desc)
{
	struct isert_conn *isert_conn = conn->context;
	struct isert_cmd *isert_cmd;
@@ -1292,6 +1303,7 @@ static struct iscsi_cmd
	isert_cmd = iscsit_priv_cmd(cmd);
	isert_cmd->conn = isert_conn;
	isert_cmd->iscsi_cmd = cmd;
	isert_cmd->rx_desc = rx_desc;

	return cmd;
}
@@ -1303,9 +1315,9 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
{
	struct iscsi_conn *conn = isert_conn->conn;
	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
	struct scatterlist *sg;
	int imm_data, imm_data_len, unsol_data, sg_nents, rc;
	bool dump_payload = false;
	unsigned int data_len;

	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
	if (rc < 0)
@@ -1314,7 +1326,10 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
	imm_data = cmd->immediate_data;
	imm_data_len = cmd->first_burst_len;
	unsol_data = cmd->unsolicited_data;
	data_len = cmd->se_cmd.data_length;

	if (imm_data && imm_data_len == data_len)
		cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
	if (rc < 0) {
		return 0;
@@ -1326,13 +1341,20 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
	if (!imm_data)
		return 0;

	sg = &cmd->se_cmd.t_data_sg[0];
	if (imm_data_len != data_len) {
		sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));

	isert_dbg("Copying Immediate SG: %p sg_nents: %u from %p imm_data_len: %d\n",
		  sg, sg_nents, &rx_desc->data[0], imm_data_len);

	sg_copy_from_buffer(sg, sg_nents, &rx_desc->data[0], imm_data_len);
		sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
				    &rx_desc->data[0], imm_data_len);
		isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
			  sg_nents, imm_data_len);
	} else {
		sg_init_table(&isert_cmd->sg, 1);
		cmd->se_cmd.t_data_sg = &isert_cmd->sg;
		cmd->se_cmd.t_data_nents = 1;
		sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
		isert_dbg("Transfer Immediate imm_data_len: %d\n",
			  imm_data_len);
	}

	cmd->write_data_done += imm_data_len;

@@ -1407,6 +1429,15 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
	if (rc < 0)
		return rc;

	/*
	 * multiple data-outs on the same command can arrive -
	 * so post the buffer before hand
	 */
	rc = isert_post_recv(isert_conn, rx_desc);
	if (rc) {
		isert_err("ib_post_recv failed with %d\n", rc);
		return rc;
	}
	return 0;
}

@@ -1479,7 +1510,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,

	switch (opcode) {
	case ISCSI_OP_SCSI_CMD:
		cmd = isert_allocate_cmd(conn);
		cmd = isert_allocate_cmd(conn, rx_desc);
		if (!cmd)
			break;

@@ -1493,7 +1524,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
					rx_desc, (unsigned char *)hdr);
		break;
	case ISCSI_OP_NOOP_OUT:
		cmd = isert_allocate_cmd(conn);
		cmd = isert_allocate_cmd(conn, rx_desc);
		if (!cmd)
			break;

@@ -1506,7 +1537,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
						(unsigned char *)hdr);
		break;
	case ISCSI_OP_SCSI_TMFUNC:
		cmd = isert_allocate_cmd(conn);
		cmd = isert_allocate_cmd(conn, rx_desc);
		if (!cmd)
			break;

@@ -1514,22 +1545,20 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
						(unsigned char *)hdr);
		break;
	case ISCSI_OP_LOGOUT:
		cmd = isert_allocate_cmd(conn);
		cmd = isert_allocate_cmd(conn, rx_desc);
		if (!cmd)
			break;

		ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
		break;
	case ISCSI_OP_TEXT:
		if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) {
		if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF)
			cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
		else
			cmd = isert_allocate_cmd(conn, rx_desc);

		if (!cmd)
			break;
		} else {
			cmd = isert_allocate_cmd(conn);
			if (!cmd)
				break;
		}

		isert_cmd = iscsit_priv_cmd(cmd);
		ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd,
@@ -1589,7 +1618,7 @@ isert_rcv_completion(struct iser_rx_desc *desc,
	struct ib_device *ib_dev = isert_conn->cm_id->device;
	struct iscsi_hdr *hdr;
	u64 rx_dma;
	int rx_buflen, outstanding;
	int rx_buflen;

	if ((char *)desc == isert_conn->login_req_buf) {
		rx_dma = isert_conn->login_req_dma;
@@ -1629,22 +1658,6 @@ isert_rcv_completion(struct iser_rx_desc *desc,
				      DMA_FROM_DEVICE);

	isert_conn->post_recv_buf_count--;
	isert_dbg("Decremented post_recv_buf_count: %d\n",
		  isert_conn->post_recv_buf_count);

	if ((char *)desc == isert_conn->login_req_buf)
		return;

	outstanding = isert_conn->post_recv_buf_count;
	if (outstanding + ISERT_MIN_POSTED_RX <= ISERT_QP_MAX_RECV_DTOS) {
		int err, count = min(ISERT_QP_MAX_RECV_DTOS - outstanding,
				ISERT_MIN_POSTED_RX);
		err = isert_post_recv(isert_conn, count);
		if (err) {
			isert_err("isert_post_recv() count: %d failed, %d\n",
			       count, err);
		}
	}
}

static int
@@ -2156,6 +2169,12 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd)
	struct ib_send_wr *wr_failed;
	int ret;

	ret = isert_post_recv(isert_conn, isert_cmd->rx_desc);
	if (ret) {
		isert_err("ib_post_recv failed with %d\n", ret);
		return ret;
	}

	ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr,
			   &wr_failed);
	if (ret) {
@@ -2950,6 +2969,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
				   &isert_cmd->tx_desc.send_wr);
		isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
		wr->send_wr_num += 1;

		rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
		if (rc) {
			isert_err("ib_post_recv failed with %d\n", rc);
			return rc;
		}
	}

	rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
@@ -2999,9 +3024,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
static int
isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
{
	int ret;
	struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
	int ret = 0;

	switch (state) {
	case ISTATE_REMOVE:
		spin_lock_bh(&conn->cmd_lock);
		list_del_init(&cmd->i_conn_node);
		spin_unlock_bh(&conn->cmd_lock);
		isert_put_cmd(isert_cmd, true);
		break;
	case ISTATE_SEND_NOPIN_WANT_RESPONSE:
		ret = isert_put_nopin(cmd, conn, false);
		break;
@@ -3106,10 +3138,10 @@ isert_setup_np(struct iscsi_np *np,
		isert_err("Unable to allocate struct isert_np\n");
		return -ENOMEM;
	}
	sema_init(&isert_np->np_sem, 0);
	mutex_init(&isert_np->np_accept_mutex);
	INIT_LIST_HEAD(&isert_np->np_accept_list);
	init_completion(&isert_np->np_login_comp);
	sema_init(&isert_np->sem, 0);
	mutex_init(&isert_np->mutex);
	INIT_LIST_HEAD(&isert_np->accepted);
	INIT_LIST_HEAD(&isert_np->pending);
	isert_np->np = np;

	/*
@@ -3125,7 +3157,7 @@ isert_setup_np(struct iscsi_np *np,
		goto out;
	}

	isert_np->np_cm_id = isert_lid;
	isert_np->cm_id = isert_lid;
	np->np_context = isert_np;

	return 0;
@@ -3214,7 +3246,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
	int ret;

accept_wait:
	ret = down_interruptible(&isert_np->np_sem);
	ret = down_interruptible(&isert_np->sem);
	if (ret)
		return -ENODEV;

@@ -3231,15 +3263,15 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
	}
	spin_unlock_bh(&np->np_thread_lock);

	mutex_lock(&isert_np->np_accept_mutex);
	if (list_empty(&isert_np->np_accept_list)) {
		mutex_unlock(&isert_np->np_accept_mutex);
	mutex_lock(&isert_np->mutex);
	if (list_empty(&isert_np->pending)) {
		mutex_unlock(&isert_np->mutex);
		goto accept_wait;
	}
	isert_conn = list_first_entry(&isert_np->np_accept_list,
			struct isert_conn, accept_node);
	list_del_init(&isert_conn->accept_node);
	mutex_unlock(&isert_np->np_accept_mutex);
	isert_conn = list_first_entry(&isert_np->pending,
			struct isert_conn, node);
	list_del_init(&isert_conn->node);
	mutex_unlock(&isert_np->mutex);

	conn->context = isert_conn;
	isert_conn->conn = conn;
@@ -3257,28 +3289,39 @@ isert_free_np(struct iscsi_np *np)
	struct isert_np *isert_np = np->np_context;
	struct isert_conn *isert_conn, *n;

	if (isert_np->np_cm_id)
		rdma_destroy_id(isert_np->np_cm_id);
	if (isert_np->cm_id)
		rdma_destroy_id(isert_np->cm_id);

	/*
	 * FIXME: At this point we don't have a good way to insure
	 * that at this point we don't have hanging connections that
	 * completed RDMA establishment but didn't start iscsi login
	 * process. So work-around this by cleaning up what ever piled
	 * up in np_accept_list.
	 * up in accepted and pending lists.
	 */
	mutex_lock(&isert_np->np_accept_mutex);
	if (!list_empty(&isert_np->np_accept_list)) {
		isert_info("Still have isert connections, cleaning up...\n");
	mutex_lock(&isert_np->mutex);
	if (!list_empty(&isert_np->pending)) {
		isert_info("Still have isert pending connections\n");
		list_for_each_entry_safe(isert_conn, n,
					 &isert_np->np_accept_list,
					 accept_node) {
					 &isert_np->pending,
					 node) {
			isert_info("cleaning isert_conn %p state (%d)\n",
				   isert_conn, isert_conn->state);
			isert_connect_release(isert_conn);
		}
	}
	mutex_unlock(&isert_np->np_accept_mutex);

	if (!list_empty(&isert_np->accepted)) {
		isert_info("Still have isert accepted connections\n");
		list_for_each_entry_safe(isert_conn, n,
					 &isert_np->accepted,
					 node) {
			isert_info("cleaning isert_conn %p state (%d)\n",
				   isert_conn, isert_conn->state);
			isert_connect_release(isert_conn);
		}
	}
	mutex_unlock(&isert_np->mutex);

	np->np_context = NULL;
	kfree(isert_np);
@@ -3345,6 +3388,41 @@ isert_wait4flush(struct isert_conn *isert_conn)
	wait_for_completion(&isert_conn->wait_comp_err);
}

/**
 * isert_put_unsol_pending_cmds() - Drop commands waiting for
 *     unsolicitate dataout
 * @conn:    iscsi connection
 *
 * We might still have commands that are waiting for unsolicited
 * dataouts messages. We must put the extra reference on those
 * before blocking on the target_wait_for_session_cmds
 */
static void
isert_put_unsol_pending_cmds(struct iscsi_conn *conn)
{
	struct iscsi_cmd *cmd, *tmp;
	static LIST_HEAD(drop_cmd_list);

	spin_lock_bh(&conn->cmd_lock);
	list_for_each_entry_safe(cmd, tmp, &conn->conn_cmd_list, i_conn_node) {
		if ((cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA) &&
		    (cmd->write_data_done < conn->sess->sess_ops->FirstBurstLength) &&
		    (cmd->write_data_done < cmd->se_cmd.data_length))
			list_move_tail(&cmd->i_conn_node, &drop_cmd_list);
	}
	spin_unlock_bh(&conn->cmd_lock);

	list_for_each_entry_safe(cmd, tmp, &drop_cmd_list, i_conn_node) {
		list_del_init(&cmd->i_conn_node);
		if (cmd->i_state != ISTATE_REMOVE) {
			struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);

			isert_info("conn %p dropping cmd %p\n", conn, cmd);
			isert_put_cmd(isert_cmd, true);
		}
	}
}

static void isert_wait_conn(struct iscsi_conn *conn)
{
	struct isert_conn *isert_conn = conn->context;
@@ -3363,8 +3441,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
	isert_conn_terminate(isert_conn);
	mutex_unlock(&isert_conn->mutex);

	isert_wait4cmds(conn);
	isert_wait4flush(isert_conn);
	isert_put_unsol_pending_cmds(conn);
	isert_wait4cmds(conn);
	isert_wait4logout(isert_conn);

	queue_work(isert_release_wq, &isert_conn->release_work);
+9 −12
Original line number Diff line number Diff line
@@ -113,7 +113,6 @@ enum {
};

struct isert_rdma_wr {
	struct list_head	wr_list;
	struct isert_cmd	*isert_cmd;
	enum iser_ib_op_code	iser_ib_op;
	struct ib_sge		*ib_sge;
@@ -134,14 +133,13 @@ struct isert_cmd {
	uint64_t		write_va;
	u64			pdu_buf_dma;
	u32			pdu_buf_len;
	u32			read_va_off;
	u32			write_va_off;
	u32			rdma_wr_num;
	struct isert_conn	*conn;
	struct iscsi_cmd	*iscsi_cmd;
	struct iser_tx_desc	tx_desc;
	struct iser_rx_desc	*rx_desc;
	struct isert_rdma_wr	rdma_wr;
	struct work_struct	comp_work;
	struct scatterlist	sg;
};

struct isert_device;
@@ -159,11 +157,10 @@ struct isert_conn {
	u64			login_req_dma;
	int			login_req_len;
	u64			login_rsp_dma;
	unsigned int		rx_desc_head;
	struct iser_rx_desc	*rx_descs;
	struct ib_recv_wr	rx_wr[ISERT_MIN_POSTED_RX];
	struct ib_recv_wr	rx_wr[ISERT_QP_MAX_RECV_DTOS];
	struct iscsi_conn	*conn;
	struct list_head	accept_node;
	struct list_head	node;
	struct completion	login_comp;
	struct completion	login_req_comp;
	struct iser_tx_desc	login_tx_desc;
@@ -222,9 +219,9 @@ struct isert_device {

struct isert_np {
	struct iscsi_np         *np;
	struct semaphore	np_sem;
	struct rdma_cm_id	*np_cm_id;
	struct mutex		np_accept_mutex;
	struct list_head	np_accept_list;
	struct completion	np_login_comp;
	struct semaphore	sem;
	struct rdma_cm_id	*cm_id;
	struct mutex		mutex;
	struct list_head	accepted;
	struct list_head	pending;
};
+3 −2
Original line number Diff line number Diff line
@@ -407,6 +407,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
			TYPERANGE_UTF8, USE_INITIAL_ONLY);
	if (!param)
		goto out;

	/*
	 * Extra parameters for ISER from RFC-5046
	 */
@@ -496,9 +497,9 @@ int iscsi_set_keys_to_negotiate(
		} else if (!strcmp(param->name, SESSIONTYPE)) {
			SET_PSTATE_NEGOTIATE(param);
		} else if (!strcmp(param->name, IFMARKER)) {
			SET_PSTATE_NEGOTIATE(param);
			SET_PSTATE_REJECT(param);
		} else if (!strcmp(param->name, OFMARKER)) {
			SET_PSTATE_NEGOTIATE(param);
			SET_PSTATE_REJECT(param);
		} else if (!strcmp(param->name, IFMARKINT)) {
			SET_PSTATE_REJECT(param);
		} else if (!strcmp(param->name, OFMARKINT)) {
+26 −19
Original line number Diff line number Diff line
@@ -62,22 +62,13 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
	struct se_session *se_sess = se_cmd->se_sess;
	struct se_node_acl *nacl = se_sess->se_node_acl;
	struct se_dev_entry *deve;
	sense_reason_t ret = TCM_NO_SENSE;

	rcu_read_lock();
	deve = target_nacl_find_deve(nacl, unpacked_lun);
	if (deve) {
		atomic_long_inc(&deve->total_cmds);

		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
		    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
			pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
				" Access for 0x%08llx\n",
				se_cmd->se_tfo->get_fabric_name(),
				unpacked_lun);
			rcu_read_unlock();
			return TCM_WRITE_PROTECTED;
		}

		if (se_cmd->data_direction == DMA_TO_DEVICE)
			atomic_long_add(se_cmd->data_length,
					&deve->write_bytes);
@@ -93,6 +84,17 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)

		percpu_ref_get(&se_lun->lun_ref);
		se_cmd->lun_ref_active = true;

		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
		    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
			pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
				" Access for 0x%08llx\n",
				se_cmd->se_tfo->get_fabric_name(),
				unpacked_lun);
			rcu_read_unlock();
			ret = TCM_WRITE_PROTECTED;
			goto ref_dev;
		}
	}
	rcu_read_unlock();

@@ -109,12 +111,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
				unpacked_lun);
			return TCM_NON_EXISTENT_LUN;
		}
		/*
		 * Force WRITE PROTECT for virtual LUN 0
		 */
		if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
		    (se_cmd->data_direction != DMA_NONE))
			return TCM_WRITE_PROTECTED;

		se_lun = se_sess->se_tpg->tpg_virt_lun0;
		se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0;
@@ -123,6 +119,15 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)

		percpu_ref_get(&se_lun->lun_ref);
		se_cmd->lun_ref_active = true;

		/*
		 * Force WRITE PROTECT for virtual LUN 0
		 */
		if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
		    (se_cmd->data_direction != DMA_NONE)) {
			ret = TCM_WRITE_PROTECTED;
			goto ref_dev;
		}
	}
	/*
	 * RCU reference protected by percpu se_lun->lun_ref taken above that
@@ -130,6 +135,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
	 * pointer can be kfree_rcu() by the final se_lun->lun_group put via
	 * target_core_fabric_configfs.c:target_fabric_port_release
	 */
ref_dev:
	se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
	atomic_long_inc(&se_cmd->se_dev->num_cmds);

@@ -140,7 +146,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
		atomic_long_add(se_cmd->data_length,
				&se_cmd->se_dev->read_bytes);

	return 0;
	return ret;
}
EXPORT_SYMBOL(transport_lookup_cmd_lun);

@@ -427,8 +433,6 @@ void core_disable_device_list_for_node(

	hlist_del_rcu(&orig->link);
	clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags);
	rcu_assign_pointer(orig->se_lun, NULL);
	rcu_assign_pointer(orig->se_lun_acl, NULL);
	orig->lun_flags = 0;
	orig->creation_time = 0;
	orig->attach_count--;
@@ -439,6 +443,9 @@ void core_disable_device_list_for_node(
	kref_put(&orig->pr_kref, target_pr_kref_release);
	wait_for_completion(&orig->pr_comp);

	rcu_assign_pointer(orig->se_lun, NULL);
	rcu_assign_pointer(orig->se_lun_acl, NULL);

	kfree_rcu(orig, rcu_head);

	core_scsi3_free_pr_reg_from_nacl(dev, nacl);
+1 −1
Original line number Diff line number Diff line
@@ -187,5 +187,5 @@ core_delete_hba(struct se_hba *hba)

bool target_sense_desc_format(struct se_device *dev)
{
	return dev->transport->get_blocks(dev) > U32_MAX;
	return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false;
}
Loading