When in the next patches we xmit from kblockd we will want to perform non-blocking IO so we don't affect other sessions while waiting for memory. This adds an arg to the task and pdu xmit functions so libiscsi can tell the drivers that support transmitting from both queuecommand and the iscsi_q wq when they can't block. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> --- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 3 ++- drivers/scsi/cxgbi/libcxgbi.c | 2 +- drivers/scsi/cxgbi/libcxgbi.h | 2 +- drivers/scsi/iscsi_tcp.c | 16 +++++++++++----- drivers/scsi/libiscsi.c | 16 ++++++++-------- drivers/scsi/libiscsi_tcp.c | 5 +++-- drivers/scsi/qedi/qedi_iscsi.c | 2 +- drivers/scsi/qla4xxx/ql4_os.c | 4 ++-- include/scsi/libiscsi_tcp.h | 2 +- include/scsi/scsi_transport_iscsi.h | 4 ++-- 12 files changed, 34 insertions(+), 26 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 07e47021a71f..244a4540dbf6 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -317,7 +317,7 @@ static int iscsi_iser_task_xmit_unsol_data(struct iscsi_conn *conn, * * Return: zero on success or escalates $error on failure. */ -static int iscsi_iser_task_xmit(struct iscsi_task *task) +static int iscsi_iser_task_xmit(struct iscsi_task *task, bool dontwait) { struct iscsi_conn *conn = task->conn; struct iscsi_iser_task *iser_task = task->dd_data; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 36fddce2786d..fbd0c6981097 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -4745,7 +4745,7 @@ static int beiscsi_mtask(struct iscsi_task *task) return 0; } -static int beiscsi_task_xmit(struct iscsi_task *task) +static int beiscsi_task_xmit(struct iscsi_task *task, bool dontwait) { struct beiscsi_io_task *io_task = task->dd_data; struct scsi_cmnd *sc = task->sc; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index a592ca8602f9..d887157c1c02 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1213,10 +1213,11 @@ bnx2i_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task) /** * bnx2i_task_xmit - transmit iscsi command to chip for further processing * @task: transport layer command structure pointer + * @dontwait: true if the driver should not block * * maps SG buffers and send request to chip/firmware in the form of SQ WQE */ -static int bnx2i_task_xmit(struct iscsi_task *task) +static int bnx2i_task_xmit(struct iscsi_task *task, bool dontwait) { struct iscsi_conn *conn = task->conn; struct iscsi_session *session = conn->session; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 411b0d386fad..6fc6cf1a0090 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2358,7 +2358,7 @@ static int cxgbi_sock_send_skb(struct cxgbi_sock *csk, struct sk_buff *skb) return len; } -int cxgbi_conn_xmit_pdu(struct iscsi_task *task) +int cxgbi_conn_xmit_pdu(struct iscsi_task *task, bool dontwait) { struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; struct cxgbi_conn *cconn = tcp_conn->dd_data; diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 3687b5c0cf90..a852dc31171a 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -604,7 +604,7 @@ void cxgbi_conn_tx_open(struct cxgbi_sock *); void cxgbi_conn_pdu_ready(struct cxgbi_sock *); int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8); int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int); -int cxgbi_conn_xmit_pdu(struct iscsi_task *); +int cxgbi_conn_xmit_pdu(struct iscsi_task *, bool); void cxgbi_cleanup_task(struct iscsi_task *task); diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 974245eab605..c2627505011d 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -279,6 +279,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_conn *conn) * iscsi_sw_tcp_xmit_segment - transmit segment * @tcp_conn: the iSCSI TCP connection * @segment: the buffer to transmnit + * @dontwait: true if we should use MSG_DONTWAIT * * This function transmits as much of the buffer as * the network layer will accept, and returns the number of @@ -289,7 +290,8 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_conn *conn) * it will retrieve the hash value and send it as well. */ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, - struct iscsi_segment *segment) + struct iscsi_segment *segment, + bool dontwait) { struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; struct socket *sk = tcp_sw_conn->sock; @@ -308,6 +310,9 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, if (segment->total_copied + segment->size < segment->total_size) flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; + if (dontwait) + flags |= MSG_DONTWAIT; + /* Use sendpage if we can; else fall back to sendmsg */ if (!segment->data) { sg = segment->sg; @@ -350,8 +355,9 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, /** * iscsi_sw_tcp_xmit - TCP transmit * @conn: iscsi connection + * @dontwait: true if we should perform nonblocking IO **/ -static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) +static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn, bool dontwait) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; @@ -360,7 +366,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) int rc = 0; while (1) { - rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment); + rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment, dontwait); /* * We may not have been able to send data because the conn * is getting stopped. libiscsi will know so propagate err @@ -411,7 +417,7 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn) return segment->total_copied - segment->total_size; } -static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task) +static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task, bool dontwait) { struct iscsi_conn *conn = task->conn; unsigned int noreclaim_flag; @@ -428,7 +434,7 @@ static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task) noreclaim_flag = memalloc_noreclaim_save(); while (iscsi_sw_tcp_xmit_qlen(conn)) { - rc = iscsi_sw_tcp_xmit(conn); + rc = iscsi_sw_tcp_xmit(conn, dontwait); if (rc == 0) { rc = -EAGAIN; break; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index fcf5c30614ba..63e0d97df50f 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -812,7 +812,7 @@ static int iscsi_send_mgmt_task(struct iscsi_task *task) if (rc) return rc; - rc = session->tt->xmit_task(task); + rc = session->tt->xmit_task(task, false); if (rc) return rc; } else { @@ -1498,7 +1498,7 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) } static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task, - bool was_requeue) + bool was_requeue, bool dontwait) { int rc; @@ -1539,7 +1539,7 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task, } spin_unlock_bh(&conn->session->frwd_lock); - rc = conn->session->tt->xmit_task(task); + rc = conn->session->tt->xmit_task(task, dontwait); spin_lock_bh(&conn->session->frwd_lock); if (!rc) { /* done with this task */ @@ -1608,7 +1608,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) } if (conn->task) { - rc = iscsi_xmit_task(conn, conn->task, false); + rc = iscsi_xmit_task(conn, conn->task, false, false); if (rc) goto done; } @@ -1630,7 +1630,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) spin_unlock_bh(&conn->session->back_lock); continue; } - rc = iscsi_xmit_task(conn, task, false); + rc = iscsi_xmit_task(conn, task, false, false); if (rc) goto done; } @@ -1652,7 +1652,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) fail_scsi_task(task, DID_ABORT); continue; } - rc = iscsi_xmit_task(conn, task, false); + rc = iscsi_xmit_task(conn, task, false, false); if (rc) goto done; /* @@ -1678,7 +1678,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) break; list_del_init(&task->running); - rc = iscsi_xmit_task(conn, task, true); + rc = iscsi_xmit_task(conn, task, true, false); if (rc) goto done; if (!list_empty(&conn->mgmtqueue)) @@ -1843,7 +1843,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) goto prepd_fault; } } - if (session->tt->xmit_task(task)) { + if (session->tt->xmit_task(task, true)) { session->cmdsn--; reason = FAILURE_SESSION_NOT_READY; goto prepd_reject; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index defe08142b75..2c783862963d 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -1060,12 +1060,13 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) /** * iscsi_tcp_task_xmit - xmit normal PDU task * @task: iscsi command task + * @dontwait: true if the driver should not wait for wmem space * * We're expected to return 0 when everything was transmitted successfully, * -EAGAIN if there's still data in the queue, or != 0 for any other kind * of error. */ -int iscsi_tcp_task_xmit(struct iscsi_task *task) +int iscsi_tcp_task_xmit(struct iscsi_task *task, bool dontwait) { struct iscsi_conn *conn = task->conn; struct iscsi_session *session = conn->session; @@ -1074,7 +1075,7 @@ int iscsi_tcp_task_xmit(struct iscsi_task *task) flush: /* Flush any pending data first. */ - rc = session->tt->xmit_pdu(task); + rc = session->tt->xmit_pdu(task, dontwait); if (rc < 0) return rc; diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 282ecb4e39bb..80a9bd4ef65e 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -827,7 +827,7 @@ static int qedi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task) return qedi_iscsi_send_generic_request(task); } -static int qedi_task_xmit(struct iscsi_task *task) +static int qedi_task_xmit(struct iscsi_task *task, bool dontwait) { struct iscsi_conn *conn = task->conn; struct qedi_conn *qedi_conn = conn->dd_data; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 955d8cb675f1..60f8c10c000d 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -137,7 +137,7 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, static void qla4xxx_session_destroy(struct iscsi_cls_session *sess); static void qla4xxx_task_work(struct work_struct *wdata); static int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t); -static int qla4xxx_task_xmit(struct iscsi_task *); +static int qla4xxx_task_xmit(struct iscsi_task *, bool); static void qla4xxx_task_cleanup(struct iscsi_task *); static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, @@ -3477,7 +3477,7 @@ static void qla4xxx_task_cleanup(struct iscsi_task *task) return; } -static int qla4xxx_task_xmit(struct iscsi_task *task) +static int qla4xxx_task_xmit(struct iscsi_task *task, bool dontwait) { struct scsi_cmnd *sc = task->sc; struct iscsi_session *sess = task->conn->session; diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index 7c8ba9d7378b..9fb97cbfa05c 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -88,7 +88,7 @@ extern int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, unsigned int offset, bool offloaded, int *status); extern void iscsi_tcp_cleanup_task(struct iscsi_task *task); extern int iscsi_tcp_task_init(struct iscsi_task *task); -extern int iscsi_tcp_task_xmit(struct iscsi_task *task); +extern int iscsi_tcp_task_xmit(struct iscsi_task *task, bool dontwait); /* segment helpers */ extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 7a0d24d3b916..d3b37d28e11a 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -108,11 +108,11 @@ struct iscsi_transport { struct iscsi_stats *stats); int (*init_task) (struct iscsi_task *task); - int (*xmit_task) (struct iscsi_task *task); + int (*xmit_task) (struct iscsi_task *task, bool dontwait); void (*cleanup_task) (struct iscsi_task *task); int (*alloc_pdu) (struct iscsi_task *task, uint8_t opcode); - int (*xmit_pdu) (struct iscsi_task *task); + int (*xmit_pdu) (struct iscsi_task *task, bool dontwait); int (*init_pdu) (struct iscsi_task *task, unsigned int offset, unsigned int count); void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt, -- 2.25.1