This has us use zero copy the PDU header. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> --- drivers/scsi/iscsi_tcp.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 261599938fc9..3bdefc4b6b17 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -306,7 +306,7 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, copy = segment->size - offset; if (segment->total_copied + segment->size < segment->total_size) - flags |= MSG_MORE; + flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST; /* Use sendpage if we can; else fall back to sendmsg */ if (!segment->data) { @@ -315,13 +315,27 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, r = tcp_sw_conn->sendpage(sk, sg_page(sg), offset, copy, flags); } else { - struct msghdr msg = { .msg_flags = flags }; - struct kvec iov = { - .iov_base = segment->data + offset, - .iov_len = copy - }; - - r = kernel_sendmsg(sk, &msg, &iov, 1, copy); + void *data = segment->data + offset; + + /* + * Make sure it's ok to send the header using zero + * copy. The case where the sg page can't be zero + * copied will also go down the sendmsg path. + */ + if (sendpage_ok(data)) { + r = tcp_sw_conn->sendpage(sk, + virt_to_page(data), + offset_in_page(data), copy, + flags); + } else { + struct msghdr msg = { .msg_flags = flags }; + struct kvec iov = { + .iov_base = data, + .iov_len = copy, + }; + + r = kernel_sendmsg(sk, &msg, &iov, 1, copy); + } } if (r < 0) { -- 2.25.1