drbd: Use sendmsg(MSG_SPLICE_PAGES) rather than sendpage()
[platform/kernel/linux-rpi.git] / drivers / block / drbd / drbd_main.c
index 83987e7..ea82d67 100644 (file)
@@ -1540,6 +1540,8 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
                    int offset, size_t size, unsigned msg_flags)
 {
        struct socket *socket = peer_device->connection->data.socket;
+       struct msghdr msg = { .msg_flags = msg_flags, };
+       struct bio_vec bvec;
        int len = size;
        int err = -EIO;
 
@@ -1549,15 +1551,17 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
         * put_page(); and would cause either a VM_BUG directly, or
         * __page_cache_release a page that would actually still be referenced
         * by someone, leading to some obscure delayed Oops somewhere else. */
-       if (drbd_disable_sendpage || !sendpage_ok(page))
-               return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
+       if (!drbd_disable_sendpage && sendpage_ok(page))
+               msg.msg_flags |= MSG_NOSIGNAL | MSG_SPLICE_PAGES;
 
-       msg_flags |= MSG_NOSIGNAL;
        drbd_update_congested(peer_device->connection);
        do {
                int sent;
 
-               sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
+               bvec_set_page(&bvec, page, offset, len);
+               iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, len);
+
+               sent = sock_sendmsg(socket, &msg);
                if (sent <= 0) {
                        if (sent == -EAGAIN) {
                                if (we_should_drop_the_connection(peer_device->connection, socket))