If we are executing a multiple pdu sequence, tell the network layer we will have more data. This also sets MSG_MORE if the app batched cmds and we know we have more than one that are going to be sent. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> --- drivers/scsi/iscsi_tcp.c | 16 +++++++++++----- drivers/scsi/libiscsi.c | 10 ++++++++++ include/scsi/libiscsi.h | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index eff5f8456ced..a85688d7ae2b 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -246,7 +246,8 @@ 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 + * @task: iscsi task we are transmitting data for + * @segment: the buffer to transmit * * This function transmits as much of the buffer as * the network layer will accept, and returns the number of @@ -257,6 +258,7 @@ 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_task *task, struct iscsi_segment *segment) { struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; @@ -273,7 +275,10 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, offset = segment->copied; copy = segment->size - offset; - if (segment->total_copied + segment->size < segment->total_size) + if (segment->total_copied + segment->size < + segment->total_size || + !(task->hdr->flags & ISCSI_FLAG_CMD_FINAL) || + !iscsi_xmit_list_is_empty(tcp_conn->iscsi_conn)) flags |= MSG_MORE; /* Use sendpage if we can; else fall back to sendmsg */ @@ -304,8 +309,9 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, /** * iscsi_sw_tcp_xmit - TCP transmit * @conn: iscsi connection + * @task: iscsi task to send data for **/ -static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) +static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn, struct iscsi_task *task) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; @@ -314,7 +320,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, task, segment); /* * We may not have been able to send data because the conn * is getting stopped. libiscsi will know so propagate err @@ -382,7 +388,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, task); if (rc == 0) { rc = -EAGAIN; break; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index dd1e1963dd05..168afcb63bcf 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1609,6 +1609,16 @@ static bool iscsi_move_tasks(struct llist_head *submit_queue, return !list_empty(exec_queue); } +inline bool iscsi_xmit_list_is_empty(struct iscsi_conn *conn) +{ + if (!list_empty(&conn->cmd_exec_list) || + !list_empty(&conn->requeue_exec_list)) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(iscsi_xmit_list_is_empty); + static void iscsi_move_all_tasks(struct iscsi_conn *conn) { iscsi_move_tasks(&conn->requeue, &conn->requeue_exec_list); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 12bdaee3b87e..f53f41f032d5 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -491,6 +491,7 @@ extern void iscsi_complete_scsi_task(struct iscsi_task *task, extern int iscsi_complete_task(struct iscsi_conn *conn, struct iscsi_task *task, struct iscsi_hdr *hdr, char *data, int datalen); extern int iscsi_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd); +extern bool iscsi_xmit_list_is_empty(struct iscsi_conn *conn); struct iscsi_sc_iter_data { struct iscsi_conn *conn; -- 2.25.1