Skip to content

Commit 7769887

Browse files
dhowellskuba-moo
authored andcommitted
nvme-tcp: Use sendmsg(MSG_SPLICE_PAGES) rather then sendpage
When transmitting data, call down into TCP using a sendmsg with MSG_SPLICE_PAGES instead of sendpage. Signed-off-by: David Howells <[email protected]> Tested-by: Sagi Grimberg <[email protected]> Acked-by: Willem de Bruijn <[email protected]> cc: Keith Busch <[email protected]> cc: Jens Axboe <[email protected]> cc: Christoph Hellwig <[email protected]> cc: Chaitanya Kulkarni <[email protected]> cc: Jens Axboe <[email protected]> cc: Matthew Wilcox <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent a1a5e87 commit 7769887

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

drivers/nvme/host/tcp.c

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -997,25 +997,28 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
997997
u32 h2cdata_left = req->h2cdata_left;
998998

999999
while (true) {
1000+
struct bio_vec bvec;
1001+
struct msghdr msg = {
1002+
.msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES,
1003+
};
10001004
struct page *page = nvme_tcp_req_cur_page(req);
10011005
size_t offset = nvme_tcp_req_cur_offset(req);
10021006
size_t len = nvme_tcp_req_cur_length(req);
10031007
bool last = nvme_tcp_pdu_last_send(req, len);
10041008
int req_data_sent = req->data_sent;
1005-
int ret, flags = MSG_DONTWAIT;
1009+
int ret;
10061010

10071011
if (last && !queue->data_digest && !nvme_tcp_queue_more(queue))
1008-
flags |= MSG_EOR;
1012+
msg.msg_flags |= MSG_EOR;
10091013
else
1010-
flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
1014+
msg.msg_flags |= MSG_MORE;
10111015

1012-
if (sendpage_ok(page)) {
1013-
ret = kernel_sendpage(queue->sock, page, offset, len,
1014-
flags);
1015-
} else {
1016-
ret = sock_no_sendpage(queue->sock, page, offset, len,
1017-
flags);
1018-
}
1016+
if (!sendpage_ok(page))
1017+
msg.msg_flags &= ~MSG_SPLICE_PAGES,
1018+
1019+
bvec_set_page(&bvec, page, len, offset);
1020+
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
1021+
ret = sock_sendmsg(queue->sock, &msg);
10191022
if (ret <= 0)
10201023
return ret;
10211024

@@ -1054,22 +1057,24 @@ static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req)
10541057
{
10551058
struct nvme_tcp_queue *queue = req->queue;
10561059
struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
1060+
struct bio_vec bvec;
1061+
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
10571062
bool inline_data = nvme_tcp_has_inline_data(req);
10581063
u8 hdgst = nvme_tcp_hdgst_len(queue);
10591064
int len = sizeof(*pdu) + hdgst - req->offset;
1060-
int flags = MSG_DONTWAIT;
10611065
int ret;
10621066

10631067
if (inline_data || nvme_tcp_queue_more(queue))
1064-
flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
1068+
msg.msg_flags |= MSG_MORE;
10651069
else
1066-
flags |= MSG_EOR;
1070+
msg.msg_flags |= MSG_EOR;
10671071

10681072
if (queue->hdr_digest && !req->offset)
10691073
nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
10701074

1071-
ret = kernel_sendpage(queue->sock, virt_to_page(pdu),
1072-
offset_in_page(pdu) + req->offset, len, flags);
1075+
bvec_set_virt(&bvec, (void *)pdu + req->offset, len);
1076+
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
1077+
ret = sock_sendmsg(queue->sock, &msg);
10731078
if (unlikely(ret <= 0))
10741079
return ret;
10751080

@@ -1093,6 +1098,8 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
10931098
{
10941099
struct nvme_tcp_queue *queue = req->queue;
10951100
struct nvme_tcp_data_pdu *pdu = nvme_tcp_req_data_pdu(req);
1101+
struct bio_vec bvec;
1102+
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_MORE, };
10961103
u8 hdgst = nvme_tcp_hdgst_len(queue);
10971104
int len = sizeof(*pdu) - req->offset + hdgst;
10981105
int ret;
@@ -1101,13 +1108,11 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
11011108
nvme_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
11021109

11031110
if (!req->h2cdata_left)
1104-
ret = kernel_sendpage(queue->sock, virt_to_page(pdu),
1105-
offset_in_page(pdu) + req->offset, len,
1106-
MSG_DONTWAIT | MSG_MORE | MSG_SENDPAGE_NOTLAST);
1107-
else
1108-
ret = sock_no_sendpage(queue->sock, virt_to_page(pdu),
1109-
offset_in_page(pdu) + req->offset, len,
1110-
MSG_DONTWAIT | MSG_MORE);
1111+
msg.msg_flags |= MSG_SPLICE_PAGES;
1112+
1113+
bvec_set_virt(&bvec, (void *)pdu + req->offset, len);
1114+
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
1115+
ret = sock_sendmsg(queue->sock, &msg);
11111116
if (unlikely(ret <= 0))
11121117
return ret;
11131118

0 commit comments

Comments
 (0)