From f80d2f0846b7b9ceb1f2a5951229ee4391edaebd Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:43 -0800 Subject: scsi: target/core: Remove the write_pending_status() callback function Due to the patch that makes TMF handling synchronous the write_pending_status() callback function is no longer called. Hence remove it. Acked-by: Felipe Balbi Reviewed-by: Sagi Grimberg Reviewed-by: Andy Grover Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Reviewed-by: Bryant G. Ly Cc: Nicholas Bellinger Cc: Mike Christie Cc: Himanshu Madhani Cc: Quinn Tran Cc: Saurav Kashyap Cc: Michael S. Tsirkin Cc: Juergen Gross Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srpt/ib_srpt.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index e9c336cff8f5..8cee8c6c6be9 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -2703,14 +2703,6 @@ static int srpt_rdma_cm_handler(struct rdma_cm_id *cm_id, return ret; } -static int srpt_write_pending_status(struct se_cmd *se_cmd) -{ - struct srpt_send_ioctx *ioctx; - - ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd); - return ioctx->state == SRPT_STATE_NEED_DATA; -} - /* * srpt_write_pending - Start data transfer from initiator to target (write). */ @@ -3806,7 +3798,6 @@ static const struct target_core_fabric_ops srpt_template = { .sess_get_index = srpt_sess_get_index, .sess_get_initiator_sid = NULL, .write_pending = srpt_write_pending, - .write_pending_status = srpt_write_pending_status, .set_default_node_attributes = srpt_set_default_node_attrs, .get_cmd_state = srpt_get_tcm_cmd_state, .queue_data_in = srpt_queue_data_in, -- cgit v1.2.3 From 8b8807b9e982e4ba05da8c0092f3c101daec5b2c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:48 -0800 Subject: scsi: RDMA/srpt: Fix handling of command / TMF submission failure If submitting an SRP IU to the target core fails, send the SCSI response "BUSY" to the initiator instead of not sending any response. Reviewed-by: Hannes Reinecke Cc: Doug Ledford Cc: Jason Gunthorpe Cc: Nicholas Bellinger Cc: Mike Christie Cc: Christoph Hellwig Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srpt/ib_srpt.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 8cee8c6c6be9..4fc901d1c0c1 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1505,7 +1505,7 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch, pr_err("0x%llx: parsing SRP descriptor table failed.\n", srp_cmd->tag); } - goto release_ioctx; + goto busy; } rc = target_submit_cmd_map_sgls(cmd, ch->sess, srp_cmd->cdb, @@ -1516,13 +1516,12 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch, if (rc != 0) { pr_debug("target_submit_cmd() returned %d for tag %#llx\n", rc, srp_cmd->tag); - goto release_ioctx; + goto busy; } return; -release_ioctx: - send_ioctx->state = SRPT_STATE_DONE; - srpt_release_cmd(cmd); +busy: + target_send_busy(cmd); } static int srp_tmr_to_tcm(int fn) -- cgit v1.2.3 From 337ec69ed761ae02a5d1226d607c487fedbd8dd7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:49 -0800 Subject: scsi: RDMA/srpt: Fix handling of TMF submission failure If submitting a TMF to the target core fails, send the "FUNCTION REJECTED" response to the initiator. Reviewed-by: Hannes Reinecke Cc: Doug Ledford Cc: Jason Gunthorpe Cc: Nicholas Bellinger Cc: Mike Christie Cc: Christoph Hellwig Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srpt/ib_srpt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 4fc901d1c0c1..0dc2df925f76 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1581,11 +1581,9 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, TARGET_SCF_ACK_KREF); if (rc != 0) { send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; - goto fail; + cmd->se_tfo->queue_tm_rsp(cmd); } return; -fail: - transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: } /** -- cgit v1.2.3 From fd1b6687091450b0ca3303c97f45ecd87401c3d7 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:50 -0800 Subject: scsi: RDMA/srpt: Rework I/O context allocation Instead of maintaining a list of free I/O contexts, use an sbitmap data structure to track which I/O contexts are in use and which are free. This makes the ib_srpt driver more consistent with other LIO drivers. Cc: Doug Ledford Cc: Jason Gunthorpe Cc: Nicholas Bellinger Cc: Mike Christie Cc: Hannes Reinecke Cc: Christoph Hellwig Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srpt/ib_srpt.c | 47 ++++++++++++++--------------------- drivers/infiniband/ulp/srpt/ib_srpt.h | 4 --- 2 files changed, 19 insertions(+), 32 deletions(-) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 0dc2df925f76..d426e01905f9 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1217,22 +1217,15 @@ static int srpt_ch_qp_err(struct srpt_rdma_ch *ch) static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) { struct srpt_send_ioctx *ioctx; - unsigned long flags; + int tag, cpu; BUG_ON(!ch); - ioctx = NULL; - spin_lock_irqsave(&ch->spinlock, flags); - if (!list_empty(&ch->free_list)) { - ioctx = list_first_entry(&ch->free_list, - struct srpt_send_ioctx, free_list); - list_del(&ioctx->free_list); - } - spin_unlock_irqrestore(&ch->spinlock, flags); - - if (!ioctx) - return ioctx; + tag = sbitmap_queue_get(&ch->sess->sess_tag_pool, &cpu); + if (tag < 0) + return NULL; + ioctx = ch->ioctx_ring[tag]; BUG_ON(ioctx->ch != ch); ioctx->state = SRPT_STATE_NEW; WARN_ON_ONCE(ioctx->recv_ioctx); @@ -1245,6 +1238,8 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) */ memset(&ioctx->cmd, 0, sizeof(ioctx->cmd)); memset(&ioctx->sense_data, 0, sizeof(ioctx->sense_data)); + ioctx->cmd.map_tag = tag; + ioctx->cmd.map_cpu = cpu; return ioctx; } @@ -2148,7 +2143,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, struct srpt_rdma_ch *ch = NULL; char i_port_id[36]; u32 it_iu_len; - int i, ret; + int i, tag_num, tag_size, ret; WARN_ON_ONCE(irqs_disabled()); @@ -2248,11 +2243,8 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, goto free_rsp_cache; } - INIT_LIST_HEAD(&ch->free_list); - for (i = 0; i < ch->rq_size; i++) { + for (i = 0; i < ch->rq_size; i++) ch->ioctx_ring[i]->ch = ch; - list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list); - } if (!sdev->use_srq) { u16 imm_data_offset = req->req_flags & SRP_IMMED_REQUESTED ? be16_to_cpu(req->imm_data_offset) : 0; @@ -2306,18 +2298,20 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, pr_debug("registering session %s\n", ch->sess_name); + tag_num = ch->rq_size; + tag_size = 1; /* ib_srpt does not use se_sess->sess_cmd_map */ if (sport->port_guid_tpg.se_tpg_wwn) - ch->sess = target_setup_session(&sport->port_guid_tpg, 0, 0, - TARGET_PROT_NORMAL, + ch->sess = target_setup_session(&sport->port_guid_tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, ch->sess_name, ch, NULL); if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess)) - ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0, - TARGET_PROT_NORMAL, i_port_id, ch, - NULL); + ch->sess = target_setup_session(&sport->port_gid_tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, i_port_id, + ch, NULL); /* Retry without leading "0x" */ if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess)) - ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0, - TARGET_PROT_NORMAL, + ch->sess = target_setup_session(&sport->port_gid_tpg, tag_num, + tag_size, TARGET_PROT_NORMAL, i_port_id + 2, ch, NULL); if (IS_ERR_OR_NULL(ch->sess)) { WARN_ON_ONCE(ch->sess == NULL); @@ -3279,7 +3273,6 @@ static void srpt_release_cmd(struct se_cmd *se_cmd) struct srpt_send_ioctx, cmd); struct srpt_rdma_ch *ch = ioctx->ch; struct srpt_recv_ioctx *recv_ioctx = ioctx->recv_ioctx; - unsigned long flags; WARN_ON_ONCE(ioctx->state != SRPT_STATE_DONE && !(ioctx->cmd.transport_state & CMD_T_ABORTED)); @@ -3295,9 +3288,7 @@ static void srpt_release_cmd(struct se_cmd *se_cmd) ioctx->n_rw_ctx = 0; } - spin_lock_irqsave(&ch->spinlock, flags); - list_add(&ioctx->free_list, &ch->free_list); - spin_unlock_irqrestore(&ch->spinlock, flags); + target_free_tag(se_cmd->se_sess, se_cmd); } /** diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index 39b3e50baf3d..ee9f20e9177a 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -207,7 +207,6 @@ struct srpt_rw_ctx { * @rw_ctxs: RDMA read/write contexts. * @imm_sg: Scatterlist for immediate data. * @rdma_cqe: RDMA completion queue element. - * @free_list: Node in srpt_rdma_ch.free_list. * @state: I/O context state. * @cmd: Target core command data structure. * @sense_data: SCSI sense data. @@ -227,7 +226,6 @@ struct srpt_send_ioctx { struct scatterlist imm_sg; struct ib_cqe rdma_cqe; - struct list_head free_list; enum srpt_command_state state; struct se_cmd cmd; u8 n_rdma; @@ -277,7 +275,6 @@ enum rdma_ch_state { * @req_lim_delta: Number of credits not yet sent back to the initiator. * @imm_data_offset: Offset from start of SRP_CMD for immediate data. * @spinlock: Protects free_list and state. - * @free_list: Head of list with free send I/O contexts. * @state: channel state. See also enum rdma_ch_state. * @using_rdma_cm: Whether the RDMA/CM or IB/CM is used for this channel. * @processing_wait_list: Whether or not cmd_wait_list is being processed. @@ -318,7 +315,6 @@ struct srpt_rdma_ch { atomic_t req_lim_delta; u16 imm_data_offset; spinlock_t spinlock; - struct list_head free_list; enum rdma_ch_state state; struct kmem_cache *rsp_buf_cache; struct srpt_send_ioctx **ioctx_ring; -- cgit v1.2.3 From 40ca8757291ca7a8775498112d320205b2a2e571 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:51 -0800 Subject: scsi: RDMA/srpt: Fix a credit leak for aborted commands Make sure that the next time a response is sent to the initiator that the credit it had allocated for the aborted request gets freed. Cc: Doug Ledford Cc: Jason Gunthorpe Cc: Nicholas Bellinger Cc: Mike Christie Cc: Hannes Reinecke Cc: Christoph Hellwig Fixes: 131e6abc674e ("target: Add TFO->abort_task for aborted task resources release") # v3.15 Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/srpt/ib_srpt.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index d426e01905f9..1a039f16d315 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -2870,8 +2870,19 @@ static void srpt_queue_tm_rsp(struct se_cmd *cmd) srpt_queue_response(cmd); } +/* + * This function is called for aborted commands if no response is sent to the + * initiator. Make sure that the credits freed by aborting a command are + * returned to the initiator the next time a response is sent by incrementing + * ch->req_lim_delta. + */ static void srpt_aborted_task(struct se_cmd *cmd) { + struct srpt_send_ioctx *ioctx = container_of(cmd, + struct srpt_send_ioctx, cmd); + struct srpt_rdma_ch *ch = ioctx->ch; + + atomic_inc(&ch->req_lim_delta); } static int srpt_queue_status(struct se_cmd *cmd) -- cgit v1.2.3 From 0300b1147e528fe6f6b0632b0ef353a87810dabf Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 25 Jan 2019 10:34:54 -0800 Subject: scsi: target/iscsi: Fix spelling of "unsolicited" Change "unsoliticed" into "unsolicited". Cc: Nicholas Bellinger Cc: Mike Christie Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Sagi Grimberg Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/isert/ib_isert.c | 2 +- drivers/target/iscsi/cxgbit/cxgbit_target.c | 2 +- drivers/target/iscsi/iscsi_target.c | 8 ++++---- drivers/target/iscsi/iscsi_target.h | 2 +- drivers/target/iscsi/iscsi_target_erl1.c | 2 +- include/target/iscsi/iscsi_transport.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/infiniband/ulp') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index e3dd13798d79..989f1ac4245c 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1186,7 +1186,7 @@ sequence_cmd: rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); if (!rc && dump_payload == false && unsol_data) - iscsit_set_unsoliticed_dataout(cmd); + iscsit_set_unsolicited_dataout(cmd); else if (dump_payload && imm_data) target_put_sess_cmd(&cmd->se_cmd); diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 25eb3891e34b..29b350a0b58f 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -960,7 +960,7 @@ after_immediate_data: target_put_sess_cmd(&cmd->se_cmd); return 0; } else if (cmd->unsolicited_data) { - iscsit_set_unsoliticed_dataout(cmd); + iscsit_set_unsolicited_dataout(cmd); } } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 98984c3adfba..7059ffdb0c20 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1194,7 +1194,7 @@ attach_cmd: } EXPORT_SYMBOL(iscsit_setup_scsi_cmd); -void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd) +void iscsit_set_unsolicited_dataout(struct iscsi_cmd *cmd) { iscsit_set_dataout_sequence_values(cmd); @@ -1202,7 +1202,7 @@ void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd) iscsit_start_dataout_timer(cmd, cmd->conn); spin_unlock_bh(&cmd->dataout_timeout_lock); } -EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout); +EXPORT_SYMBOL(iscsit_set_unsolicited_dataout); int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr) @@ -1236,7 +1236,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, */ if (!cmd->immediate_data) { if (!cmd->sense_reason && cmd->unsolicited_data) - iscsit_set_unsoliticed_dataout(cmd); + iscsit_set_unsolicited_dataout(cmd); if (!cmd->sense_reason) return 0; @@ -1308,7 +1308,7 @@ after_immediate_data: target_put_sess_cmd(&cmd->se_cmd); return rc; } else if (cmd->unsolicited_data) - iscsit_set_unsoliticed_dataout(cmd); + iscsit_set_unsolicited_dataout(cmd); } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { /* diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index 48bac0acf8c7..c95f56a3ce31 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h @@ -31,7 +31,7 @@ extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *, struct iscsi_portal_group *, bool); extern int iscsit_del_np(struct iscsi_np *); extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *); -extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); +extern void iscsit_set_unsolicited_dataout(struct iscsi_cmd *); extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *); extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *); diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 38210ab09887..c27335c29640 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -979,7 +979,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) if (cmd->se_cmd.transport_state & CMD_T_ABORTED) return 0; - iscsit_set_unsoliticed_dataout(cmd); + iscsit_set_unsolicited_dataout(cmd); } return transport_handle_cdb_direct(&cmd->se_cmd); diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index 91948bc5b185..8b4b8ce2c1ae 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -53,7 +53,7 @@ extern void iscsit_put_transport(struct iscsit_transport *); */ extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *); -extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); +extern void iscsit_set_unsolicited_dataout(struct iscsi_cmd *); extern int iscsit_process_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *, struct iscsi_scsi_req *); extern int -- cgit v1.2.3